static int pcre_sel(int cmd, dico_key_t key, const char *dict_word) { int rc = 0; char const *word = key->word; pcre *pre = key->call_data; switch (cmd) { case DICO_SELECT_BEGIN: pre = compile_pattern(word); if (!pre) return 1; key->call_data = pre; break; case DICO_SELECT_RUN: rc = pcre_exec(pre, 0, dict_word, strlen(dict_word), 0, 0, NULL, 0) >= 0; break; case DICO_SELECT_END: pcre_free(pre); break; } return rc; }
void op_indpat(mval *v, mval *dst) { int rval; icode_str indir_src; mstr *obj, object; oprtype x, getdst; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; MV_FORCE_STR(v); indir_src.str = v->str; indir_src.code = indir_pattern; if (NULL == (obj = cache_get(&indir_src))) { obj = &object; comp_init(&v->str, &getdst); source_column = 1; /* to coordinate with scanner redirection*/ rval = compile_pattern(&x, (TK_ATSIGN == TREF(window_token))); if (EXPR_FAIL == comp_fini(rval, obj, OC_IRETMVAL, &x, &getdst, v->str.len)) return; indir_src.str.addr = v->str.addr; cache_put(&indir_src, obj); /* Fall into code activation below */ } TREF(ind_result) = dst; /* Where to store return value */ comp_indr(obj); return; }
void op_indpat(mval *v, mval *dst) { bool rval; mstr *obj, object; oprtype x; error_def(ERR_INDMAXNEST); MV_FORCE_STR(v); if (!(obj = cache_get(indir_pattern, &v->str))) { comp_init(&v->str); source_column = 1; /* to coordinate with scanner redirection*/ rval = compile_pattern(&x,window_token == TK_ATSIGN); if (comp_fini(rval, &object, OC_IRETMVAL, &x, v->str.len)) { cache_put(indir_pattern, &v->str, &object); *ind_result_sp++ = dst; if (ind_result_sp >= ind_result_top) rts_error(VARLSTCNT(1) ERR_INDMAXNEST); comp_indr(&object); } } else { *ind_result_sp++ = dst; if (ind_result_sp >= ind_result_top) rts_error(VARLSTCNT(1) ERR_INDMAXNEST); comp_indr(obj); } }
int main(int argc, char **argv) { int c; int i; FILE *fp; myname = argv[0]; while ((c = getopt(argc, argv, ":iE")) != -1) { switch (c) { case 'i': ignore_case = 1; break; case 'E': extended = 1; break; case '?': usage(); break; } } if (optind == argc) /* sanity check */ usage(); compile_pattern(argv[optind]); /* compile the pattern */ if (errors) /* compile failed */ return 1; else optind++; if (optind == argc) /* no files, default to stdin */ process("standard input", stdin); else { /* loop over files */ for (i = optind; i < argc; i++) { if (strcmp(argv[i], "-") == 0) process("standard input", stdin); else if ((fp = fopen(argv[i], "r")) != NULL) { process(argv[i], fp); fclose(fp); } else { fprintf(stderr, "%s: %s: could not open: %s\n", argv[0], argv[i], strerror(errno)); errors++; } } } regfree(& pattern); return errors != 0; }
/********************************************************************* * * Function : create_pattern_spec * * Description : Creates a "pattern_spec" structure from a string. * When finished, free with free_pattern_spec(). * * Parameters : * 1 : pattern = Target pattern_spec to be filled in. * Will be zeroed before use. * 2 : buf = Source pattern, null terminated. NOTE: The * contents of this buffer are destroyed by this * function. If this function succeeds, the * buffer is copied to pattern->spec. If this * function fails, the contents of the buffer * are lost forever. * * Returns : JB_ERR_OK - Success * JB_ERR_PARSE - Cannot parse regex (Detailed message * written to system log) * *********************************************************************/ jb_err create_pattern_spec(struct pattern_spec *pattern, char *buf) { static const struct { /** The tag pattern prefix to match */ const char *prefix; /** The length of the prefix to match */ const size_t prefix_length; /** The pattern flag */ const unsigned flag; } tag_pattern[] = { { "TAG:", 4, PATTERN_SPEC_TAG_PATTERN}, { "NO-REQUEST-TAG:", 15, PATTERN_SPEC_NO_REQUEST_TAG_PATTERN}, { "NO-RESPONSE-TAG:", 16, PATTERN_SPEC_NO_RESPONSE_TAG_PATTERN} }; int i; assert(pattern); assert(buf); memset(pattern, '\0', sizeof(*pattern)); /* Remember the original specification for the CGI pages. */ pattern->spec = strdup_or_die(buf); /* Check if it's a tag pattern */ for (i = 0; i < SZ(tag_pattern); i++) { if (0 == strncmpic(pattern->spec, tag_pattern[i].prefix, tag_pattern[i].prefix_length)) { /* The regex starts after the prefix */ const char *tag_regex = buf + tag_pattern[i].prefix_length; pattern->flags |= tag_pattern[i].flag; return compile_pattern(tag_regex, NO_ANCHORING, pattern, &pattern->pattern.tag_regex); } } /* If it isn't a tag pattern it must be an URL pattern. */ pattern->flags |= PATTERN_SPEC_URL_PATTERN; return compile_url_pattern(pattern, buf); }
template<typename F1, typename F2> void split(const CharArray &input, F1 data, F2 split) { compile_pattern(); int ovector[vector_size]; size_t prev = 0; while(true) { int groups = match(input, ovector, prev); if(groups <= 0) { if(prev < input.size()) data(input.copy(prev, input.size() - prev)); return; } else { int start = ovector[0]; int stop = ovector[1]; for (int i = 0; i < groups; i++) { start = std::min(start, ovector[2 * i]); stop = std::max(stop, ovector[2 * i + 1]); } if((size_t)stop == prev) { split(start, stop); data(input.copy(prev, 1)); prev += 1; } else { data(input.copy(prev, (size_t)start - prev)); split(start, stop); prev = stop; } } } }
Lisp_Object directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, bool attrs, Lisp_Object id_format) { DIR *d; int fd; ptrdiff_t directory_nbytes; Lisp_Object list, dirfilename, encoded_directory; struct re_pattern_buffer *bufp = NULL; bool needsep = 0; ptrdiff_t count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; struct dirent *dp; #ifdef WINDOWSNT Lisp_Object w32_save = Qnil; #endif /* Don't let the compiler optimize away all copies of DIRECTORY, which would break GC; see Bug#16986. Although this is required only in the common case where GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS, it shouldn't break anything in the other cases. */ Lisp_Object volatile directory_volatile = directory; /* Because of file name handlers, these functions might call Ffuncall, and cause a GC. */ list = encoded_directory = dirfilename = Qnil; GCPRO5 (match, directory, list, dirfilename, encoded_directory); dirfilename = Fdirectory_file_name (directory); if (!NILP (match)) { CHECK_STRING (match); /* MATCH might be a flawed regular expression. Rather than catching and signaling our own errors, we just call compile_pattern to do the work for us. */ /* Pass 1 for the MULTIBYTE arg because we do make multibyte strings if the contents warrant. */ # ifdef WINDOWSNT /* Windows users want case-insensitive wildcards. */ bufp = compile_pattern (match, 0, BVAR (&buffer_defaults, case_canon_table), 0, 1); # else /* !WINDOWSNT */ bufp = compile_pattern (match, 0, Qnil, 0, 1); # endif /* !WINDOWSNT */ } /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run run_pre_post_conversion_on_str which calls Lisp directly and indirectly. */ if (STRING_MULTIBYTE (dirfilename)) dirfilename = ENCODE_FILE (dirfilename); encoded_directory = (STRING_MULTIBYTE (directory) ? ENCODE_FILE (directory) : directory); /* Now *bufp is the compiled form of MATCH; don't call anything which might compile a new regexp until we're done with the loop! */ d = open_directory (SSDATA (dirfilename), &fd); if (d == NULL) report_file_error ("Opening directory", directory); /* Unfortunately, we can now invoke expand-file-name and file-attributes on filenames, both of which can throw, so we must do a proper unwind-protect. */ record_unwind_protect_ptr (directory_files_internal_unwind, d); #ifdef WINDOWSNT if (attrs) { extern int is_slow_fs (const char *); /* Do this only once to avoid doing it (in w32.c:stat) for each file in the directory, when we call Ffile_attributes below. */ record_unwind_protect (directory_files_internal_w32_unwind, Vw32_get_true_file_attributes); w32_save = Vw32_get_true_file_attributes; if (EQ (Vw32_get_true_file_attributes, Qlocal)) { /* w32.c:stat will notice these bindings and avoid calling GetDriveType for each file. */ if (is_slow_fs (SDATA (dirfilename))) Vw32_get_true_file_attributes = Qnil; else Vw32_get_true_file_attributes = Qt; } } #endif directory_nbytes = SBYTES (directory); re_match_object = Qt; /* Decide whether we need to add a directory separator. */ if (directory_nbytes == 0 || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1))) needsep = 1; /* Loop reading blocks until EOF or error. */ for (;;) { ptrdiff_t len; bool wanted = 0; Lisp_Object name, finalname; struct gcpro gcpro1, gcpro2; errno = 0; dp = readdir (d); if (!dp) { if (errno == EAGAIN || errno == EINTR) { QUIT; continue; } break; } len = dirent_namelen (dp); name = finalname = make_unibyte_string (dp->d_name, len); GCPRO2 (finalname, name); /* Note: DECODE_FILE can GC; it should protect its argument, though. */ name = DECODE_FILE (name); len = SBYTES (name); /* Now that we have unwind_protect in place, we might as well allow matching to be interrupted. */ immediate_quit = 1; QUIT; if (NILP (match) || re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0) wanted = 1; immediate_quit = 0; if (wanted) { if (!NILP (full)) { Lisp_Object fullname; ptrdiff_t nbytes = len + directory_nbytes + needsep; ptrdiff_t nchars; fullname = make_uninit_multibyte_string (nbytes, nbytes); memcpy (SDATA (fullname), SDATA (directory), directory_nbytes); if (needsep) SSET (fullname, directory_nbytes, DIRECTORY_SEP); memcpy (SDATA (fullname) + directory_nbytes + needsep, SDATA (name), len); nchars = multibyte_chars_in_text (SDATA (fullname), nbytes); /* Some bug somewhere. */ if (nchars > nbytes) emacs_abort (); STRING_SET_CHARS (fullname, nchars); if (nchars == nbytes) STRING_SET_UNIBYTE (fullname); finalname = fullname; } else finalname = name; if (attrs) { Lisp_Object fileattrs = file_attributes (fd, dp->d_name, id_format); list = Fcons (Fcons (finalname, fileattrs), list); } else list = Fcons (finalname, list); } UNGCPRO; } block_input (); closedir (d); unblock_input (); #ifdef WINDOWSNT if (attrs) Vw32_get_true_file_attributes = w32_save; #endif /* Discard the unwind protect. */ specpdl_ptr = specpdl + count; if (NILP (nosort)) list = Fsort (Fnreverse (list), attrs ? Qfile_attributes_lessp : Qstring_lessp); (void) directory_volatile; RETURN_UNGCPRO (list); }
/********************************************************************* * * Function : compile_host_pattern * * Description : Parses and compiles a host pattern. * * Parameters : * 1 : url = Target pattern_spec to be filled in. * 2 : host_pattern = Host pattern to compile. * * Returns : JB_ERR_OK - Success * JB_ERR_MEMORY - Out of memory * JB_ERR_PARSE - Cannot parse regex * *********************************************************************/ static jb_err compile_host_pattern(struct pattern_spec *url, const char *host_pattern) { return compile_pattern(host_pattern, RIGHT_ANCHORED_HOST, url, &url->pattern.url_spec.host_regex); }
/********************************************************************* * * Function : compile_url_pattern * * Description : Compiles the three parts of an URL pattern. * * Parameters : * 1 : url = Target pattern_spec to be filled in. * 2 : buf = The url pattern to compile. Will be messed up. * * Returns : JB_ERR_OK - Success * JB_ERR_MEMORY - Out of memory * JB_ERR_PARSE - Cannot parse regex * *********************************************************************/ static jb_err compile_url_pattern(struct pattern_spec *url, char *buf) { char *p; p = strchr(buf, '/'); if (NULL != p) { /* * Only compile the regex if it consists of more than * a single slash, otherwise it wouldn't affect the result. */ if (p[1] != '\0') { /* * XXX: does it make sense to compile the slash at the beginning? */ jb_err err = compile_pattern(p, LEFT_ANCHORED, url, &url->pattern.url_spec.preg); if (JB_ERR_OK != err) { return err; } } *p = '\0'; } /* * IPv6 numeric hostnames can contain colons, thus we need * to delimit the hostname before the real port separator. * As brackets are already used in the hostname pattern, * we use angle brackets ('<', '>') instead. */ if ((buf[0] == '<') && (NULL != (p = strchr(buf + 1, '>')))) { *p++ = '\0'; buf++; if (*p == '\0') { /* IPv6 address without port number */ p = NULL; } else if (*p != ':') { /* Garbage after address delimiter */ return JB_ERR_PARSE; } } else { p = strchr(buf, ':'); } if (NULL != p) { *p++ = '\0'; url->pattern.url_spec.port_list = strdup_or_die(p); } else { url->pattern.url_spec.port_list = NULL; } if (buf[0] != '\0') { return compile_host_pattern(url, buf); } return JB_ERR_OK; }
int main(int argc, char *argv[]){ myname = argv[0]; char c; struct stat statbuf; //buffer for stat() /* i18n */ //setlocale (LC_ALL, ""); //struct lconv l = *localeconv(); //l.decimal_point = "."; struct option longopts[]={ { "user", required_argument, &do_username, 'u'}, { "tty", required_argument, &do_tty, 't'}, { "hostname", required_argument, &do_hostname, 'a'}, { "extended", no_argument, &do_extended, 'e'}, { "ignore", no_argument, &do_ignorecase, 'i'}, { "help", no_argument, NULL, 'h'}, { "version", no_argument, NULL, 'V'}, { 0, 0, 0, 0 } }; if ((argc < 2) || (argc > 18)) { version(); usage(); } while ((c=getopt_long(argc,argv,"u:t:a:reihVW;",longopts,NULL)) != -1) { switch (c) { case 'u': username = compile_pattern(optarg); if (errors) usage(); //compile failed do_username=1; break; case 't': tty = compile_pattern(optarg); if (errors) usage(); //compile failed do_tty=1; break; case 'a': hostname = compile_pattern(optarg); if (errors) usage(); //compile failed do_hostname=1; break; case 'e': do_extended = 1; break; case 'i': do_ignorecase = 1; break; case 'h': version(); usage(); case 'V': version(); exit(0); break; case 0: break; case ':': fprintf(stderr, "%s: option '-%c' requires an argument\n", myname, optopt); usage(); case '?': default: fprintf(stderr, "%s: option '-%c' is invalid\n", myname, optopt); usage(); } } //sanity check if (!do_username && !do_tty && !do_hostname){ fprintf(stderr, "%s: did not found any parametr to clean (username, hostname, tty)!\n", myname); usage(); } version(); #ifdef SUNOS if (!clear_uwbtmp(UTMPX_FILE)) printf("\033[1mutmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); if (!clear_uwbtmp(WTMPX_FILE)) printf("\033[1mwtmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); /* we able to get file attributes, so BTMPX_FILE obviously exists */ if (stat(BTMPX_FILE, &statbuf) == 0) if (!clear_uwbtmp(BTMPX_FILE)) printf("\033[1mbtmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); #else if (!clear_uwbtmp(UTMP_FILE)) printf("\033[1mutmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); if (!clear_uwbtmp(WTMP_FILE)) printf("\033[1mwtmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); /* we able to get file attributes, so BTMP_FILE obviously exists */ if (stat(BTMP_FILE, &statbuf) == 0) if (!clear_uwbtmp(BTMP_FILE)) printf("\033[1mbtmp cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); #endif if (!clear_lastlog(LASTLOG_FILE)) printf("\033[1mlastlog cleaning \t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); if (!clear_textlog(SYSLOG_FILE)) printf("\033[1msyslog cleaning \t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); if (stat(SECURE_FILE, &statbuf) == 0) //we able to get file attributes, so SECURE_FILE obviously exists if (!clear_textlog(SECURE_FILE)) printf("\033[1msecure cleaning \t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); /*APACHE LOGS */ int ii=0; while (APACHE_PATH[ii]!=NULL){ if (!clear_textlog(APACHE_PATH[ii])) printf("\033[1mapache logs cleaning \t\t\t\t\t\t\t \033[32;1m[ OK ] \033[0m\n"); ii++; } /* END APACHE LOGS */ return 0; }
int m_zwrite(void) { int4 pcount; /* parameter count */ triple *ref,*ref1,*head,*last,*count; opctype op; oprtype name,limit; mval mv; mint code; mint subscount; char c; bool pat; error_def(ERR_VAREXPECTED); error_def(ERR_RPARENMISSING); error_def(ERR_ZWRSPONE); error_def(ERR_COMMA); subscount = 0; count = 0; pat = FALSE; if (window_token == TK_CIRCUMFLEX) { advancewindow(); op = OC_GVZWRITE; } else { op = OC_LVZWRITE; } switch(window_token) { case TK_SPACE: case TK_EOL: if (op == OC_GVZWRITE) { stx_error(ERR_VAREXPECTED); return FALSE; } else { op = OC_LVPATWRITE; } head = maketriple(op); head->operand[0] = put_ilit((mint)3); ref1 = newtriple(OC_PARAMETER); head->operand[1] = put_tref(ref1); ref1->operand[0] = put_ilit(0); /* shows not from zshow */ ref = newtriple(OC_PARAMETER); ref1->operand[1] = put_tref(ref); ref->operand[0] = put_str((char *)pat_everything,sizeof_pat_everything); MV_FORCE_MVAL(&mv,ZWRITE_ASTERISK) ; ref->operand[1] = put_lit(&mv); ins_triple(head); return TRUE; case TK_IDENT: name = put_str(&window_ident.c[0],mid_len(&window_ident)); advancewindow(); break; case TK_LPAREN: if (op != OC_GVZWRITE) /* naked reference */ { stx_error(ERR_VAREXPECTED); return FALSE; } name = put_str(&window_ident.c[0], 0); break; case TK_ATSIGN: if (!indirection(&name)) return FALSE; if (op == OC_LVZWRITE && window_token != TK_LPAREN) { ref = maketriple(OC_COMMARG); ref->operand[0] = name; ref->operand[1] = put_ilit(indir_zwrite); ins_triple(ref); return TRUE; } ref = newtriple(OC_INDPAT); ref->operand[0] = name; name = put_tref(ref); break; case TK_QUESTION: advancewindow(); source_column = last_source_column; if (!compile_pattern(&name,FALSE)) return FALSE; if (op == OC_LVZWRITE) op = OC_LVPATWRITE; pat = TRUE; break; default: stx_error(ERR_VAREXPECTED); return FALSE; } head = maketriple(op); last = newtriple(OC_PARAMETER); head->operand[1] = put_tref(last); pcount = 1; if (op == OC_LVPATWRITE || op == OC_GVZWRITE) { pcount++; last->operand[0] = put_ilit((op == OC_GVZWRITE ? pat : 0)); ref = newtriple(OC_PARAMETER); last->operand[1] = put_tref(ref); last = ref; if (op == OC_GVZWRITE) { pcount++; count = last; ref = newtriple(OC_PARAMETER); last->operand[1] = put_tref(ref); last = ref; } } last->operand[0] = name; if (window_token != TK_LPAREN) { pcount++; if (pat) { MV_FORCE_MVAL(&mv,ZWRITE_END) ; } else { subscount++ ; MV_FORCE_MVAL(&mv,ZWRITE_ASTERISK) ; } last->operand[1] = put_lit(&mv); head->operand[0] = put_ilit(pcount); if (count) count->operand[0] = put_ilit(subscount); ins_triple(head); return TRUE; } advancewindow(); for(;;) { ref = newtriple(OC_PARAMETER); last->operand[1] = put_tref(ref); switch (window_token) { case TK_RPAREN: dqdel(ref,exorder); advancewindow(); MV_FORCE_MVAL(&mv,ZWRITE_END) ; last->operand[1] = put_lit(&mv); pcount++; head->operand[0] = put_ilit((mint)pcount); if (count) count->operand[0] = put_ilit(subscount); ins_triple(head); return TRUE; case TK_ASTERISK: dqdel(ref,exorder); advancewindow(); if (window_token != TK_RPAREN) { stx_error(ERR_RPARENMISSING); return FALSE; } advancewindow(); MV_FORCE_MVAL(&mv,ZWRITE_ASTERISK) ; last->operand[1] = put_lit(&mv); pcount++; subscount++; head->operand[0] = put_ilit((mint)pcount); if (count) count->operand[0] = put_ilit(subscount); ins_triple(head); return TRUE; case TK_QUESTION: advancewindow(); source_column = last_source_column; if (!compile_pattern(&limit,FALSE)) return FALSE; if (window_token != TK_COMMA && window_token != TK_RPAREN) { stx_error(ERR_ZWRSPONE); return FALSE; } if (window_token == TK_COMMA) advancewindow(); subscount++; MV_FORCE_MVAL(&mv,ZWRITE_PATTERN) ; ref->operand[0] = put_lit(&mv); pcount++; ref1 = newtriple(OC_PARAMETER); ref->operand[1] = put_tref(ref1); ref1->operand[0] = limit; last = ref1; pcount++; continue; case TK_COLON: if ((c = director_token) != TK_RPAREN) { if (c != TK_COMMA) { advancewindow(); MV_FORCE_MVAL(&mv,ZWRITE_UPPER) ; ref->operand[0] = put_lit(&mv); pcount++; subscount++; break; } advancewindow(); } /* caution: fall through */ case TK_COMMA: advancewindow(); MV_FORCE_MVAL(&mv,ZWRITE_ALL) ; ref->operand[0] = put_lit(&mv); pcount++; subscount++; last = ref; continue; default: if (!expr(&limit)) return FALSE; subscount++; last = newtriple(OC_PARAMETER); ref->operand[1] = put_tref(last); last->operand[0] = limit; pcount++; if ((c = window_token) == TK_COLON) { code = ZWRITE_LOWER; advancewindow(); c = window_token; } else code = ZWRITE_VAL; switch (c) { case TK_COMMA: advancewindow(); /* caution: fall through */ case TK_RPAREN: MV_FORCE_MVAL(&mv,code) ; ref->operand[0] = put_lit(&mv); pcount++; continue; default: if (code == ZWRITE_VAL) { stx_error(ERR_COMMA); return FALSE; } MV_FORCE_MVAL(&mv,ZWRITE_BOTH) ; ref->operand[0] = put_lit(&mv); pcount++; ref = last; break; } break; } if (!expr(&limit)) return FALSE; last = newtriple(OC_PARAMETER); ref->operand[1] = put_tref(last); last->operand[0] = limit; pcount++; if (window_token == TK_COMMA) { advancewindow(); } } }
Lisp_Object directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, int attrs, Lisp_Object id_format) { DIR *d; int directory_nbytes; Lisp_Object list, dirfilename, encoded_directory; struct re_pattern_buffer *bufp = NULL; int needsep = 0; int count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; DIRENTRY *dp; #ifdef WINDOWSNT Lisp_Object w32_save = Qnil; #endif /* Because of file name handlers, these functions might call Ffuncall, and cause a GC. */ list = encoded_directory = dirfilename = Qnil; GCPRO5 (match, directory, list, dirfilename, encoded_directory); dirfilename = Fdirectory_file_name (directory); if (!NILP (match)) { CHECK_STRING (match); /* MATCH might be a flawed regular expression. Rather than catching and signaling our own errors, we just call compile_pattern to do the work for us. */ /* Pass 1 for the MULTIBYTE arg because we do make multibyte strings if the contents warrant. */ # ifdef WINDOWSNT /* Windows users want case-insensitive wildcards. */ bufp = compile_pattern (match, 0, buffer_defaults.case_canon_table, 0, 1); # else /* !WINDOWSNT */ bufp = compile_pattern (match, 0, Qnil, 0, 1); # endif /* !WINDOWSNT */ } /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run run_pre_post_conversion_on_str which calls Lisp directly and indirectly. */ if (STRING_MULTIBYTE (dirfilename)) dirfilename = ENCODE_FILE (dirfilename); encoded_directory = (STRING_MULTIBYTE (directory) ? ENCODE_FILE (directory) : directory); /* Now *bufp is the compiled form of MATCH; don't call anything which might compile a new regexp until we're done with the loop! */ BLOCK_INPUT; d = opendir (SDATA (dirfilename)); UNBLOCK_INPUT; if (d == NULL) report_file_error ("Opening directory", Fcons (directory, Qnil)); /* Unfortunately, we can now invoke expand-file-name and file-attributes on filenames, both of which can throw, so we must do a proper unwind-protect. */ record_unwind_protect (directory_files_internal_unwind, make_save_value (d, 0)); #ifdef WINDOWSNT if (attrs) { extern int is_slow_fs (const char *); /* Do this only once to avoid doing it (in w32.c:stat) for each file in the directory, when we call Ffile_attributes below. */ record_unwind_protect (directory_files_internal_w32_unwind, Vw32_get_true_file_attributes); w32_save = Vw32_get_true_file_attributes; if (EQ (Vw32_get_true_file_attributes, Qlocal)) { /* w32.c:stat will notice these bindings and avoid calling GetDriveType for each file. */ if (is_slow_fs (SDATA (dirfilename))) Vw32_get_true_file_attributes = Qnil; else Vw32_get_true_file_attributes = Qt; } } #endif directory_nbytes = SBYTES (directory); re_match_object = Qt; /* Decide whether we need to add a directory separator. */ if (directory_nbytes == 0 || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1))) needsep = 1; /* Loop reading blocks until EOF or error. */ for (;;) { errno = 0; dp = readdir (d); if (dp == NULL && (0 #ifdef EAGAIN || errno == EAGAIN #endif #ifdef EINTR || errno == EINTR #endif )) { QUIT; continue; } if (dp == NULL) break; if (DIRENTRY_NONEMPTY (dp)) { int len; int wanted = 0; Lisp_Object name, finalname; struct gcpro gcpro1, gcpro2; len = NAMLEN (dp); name = finalname = make_unibyte_string (dp->d_name, len); GCPRO2 (finalname, name); /* Note: DECODE_FILE can GC; it should protect its argument, though. */ name = DECODE_FILE (name); len = SBYTES (name); /* Now that we have unwind_protect in place, we might as well allow matching to be interrupted. */ immediate_quit = 1; QUIT; if (NILP (match) || (0 <= re_search (bufp, SDATA (name), len, 0, len, 0))) wanted = 1; immediate_quit = 0; if (wanted) { if (!NILP (full)) { Lisp_Object fullname; int nbytes = len + directory_nbytes + needsep; int nchars; fullname = make_uninit_multibyte_string (nbytes, nbytes); memcpy (SDATA (fullname), SDATA (directory), directory_nbytes); if (needsep) SSET (fullname, directory_nbytes, DIRECTORY_SEP); memcpy (SDATA (fullname) + directory_nbytes + needsep, SDATA (name), len); nchars = chars_in_text (SDATA (fullname), nbytes); /* Some bug somewhere. */ if (nchars > nbytes) abort (); STRING_SET_CHARS (fullname, nchars); if (nchars == nbytes) STRING_SET_UNIBYTE (fullname); finalname = fullname; } else finalname = name; if (attrs) { /* Construct an expanded filename for the directory entry. Use the decoded names for input to Ffile_attributes. */ Lisp_Object decoded_fullname, fileattrs; struct gcpro gcpro1, gcpro2; decoded_fullname = fileattrs = Qnil; GCPRO2 (decoded_fullname, fileattrs); /* Both Fexpand_file_name and Ffile_attributes can GC. */ decoded_fullname = Fexpand_file_name (name, directory); fileattrs = Ffile_attributes (decoded_fullname, id_format); list = Fcons (Fcons (finalname, fileattrs), list); UNGCPRO; } else list = Fcons (finalname, list); } UNGCPRO; } } BLOCK_INPUT; closedir (d); UNBLOCK_INPUT; #ifdef WINDOWSNT if (attrs) Vw32_get_true_file_attributes = w32_save; #endif /* Discard the unwind protect. */ specpdl_ptr = specpdl + count; if (NILP (nosort)) list = Fsort (Fnreverse (list), attrs ? Qfile_attributes_lessp : Qstring_lessp); RETURN_UNGCPRO (list); }
static WIN32_FIND_DATA * mswindows_get_files (char *dirfile, int nowild, Lisp_Object pattern, int hide_dot, int hide_system, int *nfiles) { WIN32_FIND_DATA *files; int array_size; struct re_pattern_buffer *bufp = NULL; int findex, len; char win32pattern[MAXNAMLEN+3]; HANDLE fh; int errm; /* * Much of the following code and comments were taken from dired.c. * Yes, this is something of a waste, but we want speed, speed, SPEED. */ files = NULL; array_size = *nfiles = 0; while (1) { if (!NILP(pattern)) { /* PATTERN might be a flawed regular expression. Rather than catching and signalling our own errors, we just call compile_pattern to do the work for us. */ bufp = compile_pattern (pattern, 0, Qnil, 0, ERROR_ME); } /* Now *bufp is the compiled form of PATTERN; don't call anything which might compile a new regexp until we're done with the loop! */ /* Initialize file info array */ array_size = 100; /* initial size */ files = xmalloc(array_size * sizeof (WIN32_FIND_DATA)); /* for Win32, we need to insure that the pathname ends with "\*". */ strcpy (win32pattern, dirfile); if (!nowild) { len = strlen (win32pattern) - 1; if (!IS_DIRECTORY_SEP (win32pattern[len])) strcat (win32pattern, "\\"); strcat (win32pattern, "*"); } /* * Here, we use FindFirstFile()/FindNextFile() instead of opendir(), * xemacs_stat(), & friends, because xemacs_stat() is VERY expensive in * terms of time. Hence, we take the time to write complicated * Win32-specific code, instead of simple Unix-style stuff. */ findex = 0; fh = INVALID_HANDLE_VALUE; errm = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); while (1) { int len; char *filename; int result; if (fh == INVALID_HANDLE_VALUE) { fh = FindFirstFile(win32pattern, &files[findex]); if (fh == INVALID_HANDLE_VALUE) { SetErrorMode (errm); report_file_error ("Opening directory", list1(build_string(dirfile))); } } else { if (!FindNextFile(fh, &files[findex])) { if (GetLastError() == ERROR_NO_MORE_FILES) { break; } FindClose(fh); SetErrorMode (errm); report_file_error ("Reading directory", list1(build_string(dirfile))); } } filename = files[findex].cFileName; if (!NILP(Vmswindows_downcase_file_names)) { strlwr(filename); } len = strlen(filename); result = (NILP(pattern) || (0 <= re_search (bufp, filename, len, 0, len, 0))); if (result) { if ( ! (filename[0] == '.' && ((hide_system && (filename[1] == '\0' || (filename[1] == '.' && filename[2] == '\0'))) || hide_dot))) { if (++findex >= array_size) { array_size = findex * 2; files = xrealloc(files, array_size * sizeof(WIN32_FIND_DATA)); } } } } if (fh != INVALID_HANDLE_VALUE) { FindClose (fh); } *nfiles = findex; break; } SetErrorMode (errm); return (files); }