const eString &eString::operator = (const char *ch) { if (ch == NULL) { eStr_Len = 0; eStr_Str = new char [1]; eStr_Str[0] = 0; fn_free = free; return *this; } if (ch == this->eStr_Str) return *this; eStr_Len = strlen(ch); fn_free(eStr_Str); fn_free = free; eStr_Str = new char [(eStr_Len + 1)]; strncpy(eStr_Str, ch, eStr_Len); eStr_Str[eStr_Len] = 0; return *this; }
const eString &eString::operator = (const eString &str) { if (&str == this) return *this; eStr_Len = str.eStr_Len; fn_free(eStr_Str); fn_free = free; eStr_Str = new char[(eStr_Len + 1)]; strncpy(eStr_Str, str.eStr_Str, eStr_Len); eStr_Str[eStr_Len] = 0; return *this; }
const eString &eString::operator += (const char *ch) { char *tempstr = new char [(eStr_Len + 1)]; strncpy(tempstr, eStr_Str, eStr_Len); tempstr[eStr_Len] = 0; eStr_Len += strlen(ch); fn_free(eStr_Str); fn_free = free; eStr_Str = new char [(eStr_Len + 1)]; strncpy(eStr_Str, tempstr, strlen(tempstr)); strncpy((&(eStr_Str[strlen(tempstr)])), ch, strlen(ch)); eStr_Str[eStr_Len] = 0; delete [] tempstr; tempstr = NULL; return *this; }
const eString &eString::operator = (const int ch) { union { int i; char ch; } GetCh; GetCh.i = ch; fn_free(eStr_Str); fn_free = free; eStr_Len = ((GetCh.ch == 0) ? (0) : (1)); eStr_Str = new char [((GetCh.ch == 0) ? (1) : (2))]; eStr_Str[0] = GetCh.ch; if (GetCh.ch != 0) eStr_Str[1] = 0; return *this; }
const eString &eString::operator += (const int ch) { if (ch == 0) return *this; char *tempstr = new char [(eStr_Len + 1)]; strncpy(tempstr, eStr_Str, eStr_Len); tempstr[eStr_Len] = 0; eStr_Len += 1; fn_free(eStr_Str); fn_free = free; eStr_Str = new char [(eStr_Len + 1)]; strncpy(eStr_Str, tempstr, strlen(tempstr)); eStr_Str[strlen(tempstr)] = ch; eStr_Str[eStr_Len] = 0; delete [] tempstr; tempstr = NULL; return *this; }
static void do_subdir (kpathsea kpse, str_llist_type *str_list_ptr, string elt, unsigned elt_length, string post) { #ifdef WIN32 WIN32_FIND_DATAW find_file_data; HANDLE hnd; int proceed; int nlinks = 2; #else DIR *dir; struct dirent *e; #endif /* not WIN32 */ fn_type name; /* Some old compilers don't allow aggregate initialization. */ name = fn_copy0 (elt, elt_length); assert (IS_DIR_SEP_CH (elt[elt_length - 1]) || IS_DEVICE_SEP (elt[elt_length - 1])); #if defined (WIN32) strcpy(dirname, FN_STRING(name)); strcat(dirname, "/*.*"); /* "*.*" or "*" -- seems equivalent. */ get_wstring_from_fsyscp(dirname, dirnamew); hnd = FindFirstFileW(dirnamew, &find_file_data); if (hnd == INVALID_HANDLE_VALUE) { fn_free(&name); return; } /* Include top level before subdirectories, if nothing to match. */ if (*post == 0) dir_list_add (str_list_ptr, FN_STRING (name)); else { /* If we do have something to match, see if it exists. For example, POST might be `pk/ljfour', and they might have a directory `$TEXMF/fonts/pk/ljfour' that we should find. */ fn_str_grow (&name, post); expand_elt (kpse, str_list_ptr, FN_STRING (name), elt_length); fn_shrink_to (&name, elt_length); } proceed = 1; while (proceed) { if (find_file_data.cFileName[0] != L'.') { int links; /* Construct the potential subdirectory name. */ potname = get_fsyscp_from_wstring(find_file_data.cFileName, potname=NULL); fn_str_grow (&name, potname); free(potname); /* Maybe we have cached the leafness of this directory. The function will return 0 if unknown, else the actual (Unix-like) value. */ links = kpathsea_dir_links (kpse, FN_STRING (name), 0); if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { unsigned potential_len = FN_LENGTH (name); /* in any case, compute the leafness */ nlinks++; /* It's a directory, so append the separator. */ fn_str_grow (&name, DIR_SEP_STRING); if (*post != 0) { fn_str_grow (&name, post); /* Unfortunately we can't check if the new element is a leaf directory, because we don't have a directory name here, we just have a path spec. This means we may descend into a leaf directory cm/pk, if the spec is ...fonts//pk//. */ expand_elt (kpse, str_list_ptr, FN_STRING (name), potential_len); fn_shrink_to (&name, potential_len); } /* Should we recurse? To see if the subdirectory is a leaf, check if it has two links (one for . and one for ..). This means that symbolic links to directories do not affect the leaf-ness. This is arguably wrong, but the only alternative I know of is to stat every entry in the directory, and that is unacceptably slow. */ if (links == 0 || links > 2) /* All criteria are met; find subdirectories. */ do_subdir (kpse, str_list_ptr, FN_STRING (name), potential_len, post); else if (*post == 0) /* Nothing to match, no recursive subdirectories to look for: we're done with this branch. Add it. */ dir_list_add (str_list_ptr, FN_STRING (name)); } fn_shrink_to (&name, elt_length); } proceed = FindNextFileW (hnd, &find_file_data); } /* Update the leafness of name. */ kpathsea_dir_links(kpse, FN_STRING(name), nlinks); fn_free (&name); FindClose(hnd); #else /* not WIN32 */ /* If we can't open it, quit. */ dir = opendir (FN_STRING (name)); if (dir == NULL) { fn_free (&name); return; } /* Include top level before subdirectories, if nothing to match. */ if (*post == 0) dir_list_add (str_list_ptr, FN_STRING (name)); else { /* If we do have something to match, see if it exists. For example, POST might be `pk/ljfour', and they might have a directory `$TEXMF/fonts/pk/ljfour' that we should find. */ fn_str_grow (&name, post); expand_elt (kpse, str_list_ptr, FN_STRING (name), elt_length); fn_shrink_to (&name, elt_length); } while ((e = readdir (dir)) != NULL) { /* If it begins with a `.', never mind. (This allows ``hidden'' directories that the algorithm won't find.) */ if (e->d_name[0] != '.') { int links; /* Construct the potential subdirectory name. */ fn_str_grow (&name, e->d_name); /* If we can't stat it, or if it isn't a directory, continue. */ links = kpathsea_dir_links (kpse, FN_STRING (name), 0); if (links >= 0) { unsigned potential_len = FN_LENGTH (name); /* It's a directory, so append the separator. */ fn_str_grow (&name, DIR_SEP_STRING); if (*post != 0) { fn_str_grow (&name, post); /* Unfortunately we can't check if the new element is a leaf directory, because we don't have a directory name here, we just have a path spec. This means we may descend into a leaf directory cm/pk, if the spec is ...fonts//pk//. */ expand_elt (kpse, str_list_ptr, FN_STRING (name), potential_len); fn_shrink_to (&name, potential_len); } /* Should we recurse? To see if the subdirectory is a leaf, check if it has two links (one for . and one for ..). This means that symbolic links to directories do not affect the leaf-ness. This is arguably wrong, but the only alternative I know of is to stat every entry in the directory, and that is unacceptably slow. The #ifdef here makes all this configurable at compile-time, so that if we're using VMS directories or some such, we can still find subdirectories, even if it is much slower. */ #ifdef ST_NLINK_TRICK /* With SAS/C++ 6.55 on the Amiga, stat sets the st_nlink field to -1 for a file, or to 1 for a directory. Cygwin 1.7 also leaves st_nlink as 1: http://cygwin.com/ml/cygwin-developers/2008-04/msg00110.html */ if (links != 2) #endif /* ST_NLINK_TRICK */ /* All criteria are met; find subdirectories. */ do_subdir (kpse, str_list_ptr, FN_STRING (name), potential_len, post); #ifdef ST_NLINK_TRICK else if (*post == 0) /* Nothing to match, no recursive subdirectories to look for: we're done with this branch. Add it. */ dir_list_add (str_list_ptr, FN_STRING (name)); #endif } /* Remove the directory entry we just checked from `name'. */ fn_shrink_to (&name, elt_length); } } fn_free (&name); xclosedir (dir); #endif /* not WIN32 */ }
eString::~eString() { fn_free(eStr_Str); eStr_Str = NULL; eStr_Len = 0; }
static void do_subdir P4C(str_llist_type *, str_list_ptr, const_string, elt, unsigned, elt_length, const_string, post) { #ifdef WIN32 WIN32_FIND_DATA find_file_data; HANDLE hnd; int proceed; #else DIR *dir; struct dirent *e; #endif /* not WIN32 */ fn_type name; /* Some old compilers don't allow aggregate initialization. */ name = fn_copy0 (elt, elt_length); assert (IS_DIR_SEP (elt[elt_length - 1]) || IS_DEVICE_SEP (elt[elt_length - 1])); #if defined (WIN32) strcpy(dirname, FN_STRING(name)); strcat(dirname, "/*.*"); /* "*.*" or "*" -- seems equivalent. */ hnd = FindFirstFile(dirname, &find_file_data); if (hnd == INVALID_HANDLE_VALUE) { fn_free(&name); return; } /* Include top level before subdirectories, if nothing to match. */ if (*post == 0) dir_list_add (str_list_ptr, FN_STRING (name)); else { /* If we do have something to match, see if it exists. For example, POST might be `pk/ljfour', and they might have a directory `$TEXMF/fonts/pk/ljfour' that we should find. */ fn_str_grow (&name, post); expand_elt (str_list_ptr, FN_STRING (name), elt_length); fn_shrink_to (&name, elt_length); } proceed = 1; while (proceed) { if (find_file_data.cFileName[0] != '.') { /* Construct the potential subdirectory name. */ fn_str_grow (&name, find_file_data.cFileName); if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { unsigned potential_len = FN_LENGTH (name); /* It's a directory, so append the separator. */ fn_str_grow (&name, DIR_SEP_STRING); do_subdir (str_list_ptr, FN_STRING (name), potential_len, post); } fn_shrink_to (&name, elt_length); } proceed = FindNextFile (hnd, &find_file_data); } fn_free (&name); FindClose(hnd); #else /* not WIN32 */ /* If we can't open it, quit. */ dir = opendir (FN_STRING (name)); if (dir == NULL) { fn_free (&name); return; } /* Include top level before subdirectories, if nothing to match. */ if (*post == 0) dir_list_add (str_list_ptr, FN_STRING (name)); else { /* If we do have something to match, see if it exists. For example, POST might be `pk/ljfour', and they might have a directory `$TEXMF/fonts/pk/ljfour' that we should find. */ fn_str_grow (&name, post); expand_elt (str_list_ptr, FN_STRING (name), elt_length); fn_shrink_to (&name, elt_length); } while ((e = readdir (dir)) != NULL) { /* If it begins with a `.', never mind. (This allows ``hidden'' directories that the algorithm won't find.) */ if (e->d_name[0] != '.') { int links; /* Construct the potential subdirectory name. */ fn_str_grow (&name, e->d_name); /* If we can't stat it, or if it isn't a directory, continue. */ links = dir_links (FN_STRING (name)); if (links >= 0) { unsigned potential_len = FN_LENGTH (name); /* It's a directory, so append the separator. */ fn_str_grow (&name, DIR_SEP_STRING); /* Should we recurse? To see if the subdirectory is a leaf, check if it has two links (one for . and one for ..). This means that symbolic links to directories do not affect the leaf-ness. This is arguably wrong, but the only alternative I know of is to stat every entry in the directory, and that is unacceptably slow. The #ifdef here makes all this configurable at compile-time, so that if we're using VMS directories or some such, we can still find subdirectories, even if it is much slower. */ #ifdef ST_NLINK_TRICK #ifdef AMIGA /* With SAS/C++ 6.55 on the Amiga, `stat' sets the `st_nlink' field to -1 for a file, or to 1 for a directory. */ if (links == 1) #else if (links > 2) #endif /* not AMIGA */ #endif /* not ST_NLINK_TRICK */ /* All criteria are met; find subdirectories. */ do_subdir (str_list_ptr, FN_STRING (name), potential_len, post); #ifdef ST_NLINK_TRICK else if (*post == 0) /* Nothing to match, no recursive subdirectories to look for: we're done with this branch. Add it. */ dir_list_add (str_list_ptr, FN_STRING (name)); #endif } /* Remove the directory entry we just checked from `name'. */ fn_shrink_to (&name, elt_length); } } fn_free (&name); xclosedir (dir); #endif /* not WIN32 */ }
/* * kw_expand -- expand src into dst with given n value for $n (or $N) * * n == -1 means expand src into a reglob * if gz is true, include ".gz" extension * * returns true if template contains $n or $N (implying rotation of files) */ boolean_t kw_expand(struct fn *src, struct fn *dst, int n, boolean_t gz) { int c; char buf[MAXDIGITS]; boolean_t hasn = B_FALSE; struct fn *kw = fn_new(NULL); char *ptr; struct tm *gmt_tm = localtime(&Now); while ((c = fn_getc(src)) != '\0') switch (c) { case '.': case '(': case ')': case '^': case '+': case '{': case '}': /* when building an re, escape with a backslash */ if (n < 0) fn_putc(dst, '\\'); fn_putc(dst, c); break; case '?': /* when building an re, change '?' to a single dot */ if (n < 0) fn_putc(dst, '.'); break; case '*': /* when building an re, change '*' to ".*" */ if (n < 0) fn_putc(dst, '.'); fn_putc(dst, '*'); break; case '$': /* '$' marks the start of a keyword */ switch (c = fn_getc(src)) { case '$': /* double '$' stands for a single '$' */ if (n < 0) fn_putc(dst, '\\'); fn_putc(dst, '$'); break; case '#': /* * $# expands to nothing, but forces an end * of keyword, allow juxtaposition of a * keyword with lower-case characters */ break; case 'n': case 'N': if (c == 'N' || !islower(fn_peekc(src))) { /* * we've found $n or $N, if we're * building an re, build one that * matches a number, otherwise * expand the keyword to the n * passed in to this function */ hasn = B_TRUE; if (n < 0) fn_puts(dst, "([0-9]+)$0"); else { (void) snprintf(buf, MAXDIGITS, "%d", (c == 'n') ? n : n + 1); fn_puts(dst, buf); } break; } /*FALLTHROUGH*/ default: /* gather up the keyword name */ fn_renew(kw, NULL); fn_putc(kw, c); while (islower(fn_peekc(src))) fn_putc(kw, fn_getc(src)); /* lookup keyword */ if ((ptr = (char *)lut_lookup(Keywords, fn_s(kw))) == NULL) { /* nope, copy it unexpanded */ if (n < 0) fn_putc(dst, '\\'); fn_putc(dst, '$'); fn_putfn(dst, kw); } else fn_puts(dst, ptr); } break; case '%': /* * % sequence for strftime(), if we're building * an re, we take our best guess at the re for * this sequence, otherwise we pass it to strftime() */ if (n < 0) { /* * the regex for a percent sequence is * usually just ".*" unless it is one * of the common cases we know about * that are numeric. in those cases, we * tighten up the regex to just match digits. * * while it is gross that we embed knowledge * of strftime() sequences here, they are * specified in a standard so aren't * expected to change often, and it *really* * cuts down on the possibility that we'll * expire a file that isn't an old log file. */ if ((c = fn_getc(src)) == 'E' || c == 'O') { c = fn_getc(src); fn_puts(dst, ".*"); } else switch (c) { case 'd': case 'g': case 'G': case 'H': case 'I': case 'j': case 'm': case 'M': case 'S': case 'u': case 'U': case 'V': case 'w': case 'W': case 'y': case 'Y': /* pure numeric cases */ fn_puts(dst, "[0-9]+"); break; case 'e': case 'k': case 'l': /* possible space then num */ fn_puts(dst, " *[0-9]+"); break; case 'D': /* %m/%d/%y */ /* adds slashes! */ fn_puts(dst, "[0-9]+/[0-9]+/[0-9]+"); break; case 'R': /* %H:%M */ fn_puts(dst, "[0-9]+:[0-9]+"); break; case 'T': /* %H:%M:%S */ fn_puts(dst, "[0-9]+:[0-9]+:[0-9]+"); break; default: fn_puts(dst, ".*"); } } else { char tbuf[4]; /* copy % sequence to tbuf */ tbuf[0] = '%'; tbuf[1] = fn_getc(src); if (tbuf[1] == 'E' || tbuf[1] == 'O') { /* "extended" sequence */ tbuf[2] = fn_getc(src); tbuf[3] = '\0'; } else tbuf[2] = '\0'; if (strftime(buf, MAXDIGITS, tbuf, gmt_tm) == 0) /* just copy %x */ fn_puts(dst, tbuf); else fn_puts(dst, buf); } break; default: /* nothing special, just copy it */ fn_putc(dst, c); } if (gz) { if (n < 0) fn_puts(dst, "(\\.gz){0,1}"); else fn_puts(dst, ".gz"); } fn_free(kw); return (hasn); }