Compare commits

...

5 Commits

Author SHA1 Message Date
Dianne Skoll e394f402f8 Set release date.
Remind unit tests / tests (push) Successful in 32s
2024-12-16 09:31:02 -05:00
Dianne Skoll 5a2914f6c7 Start hash tables with 7 buckets instead of 17; print more detailed hash stats with -ds; consistently use ErrFp instead of stderr
Remind unit tests / tests (push) Successful in 32s
2024-12-14 11:52:16 -05:00
Dianne Skoll a19b009f7c Fix man page typo and cppcheck warnings.
Remind unit tests / tests (push) Successful in 32s
2024-12-13 15:22:46 -05:00
Dianne Skoll 6373ae8ca5 Update release notes. 2024-12-13 15:08:54 -05:00
Dianne Skoll b8c4786b33 Allow INCLUDE/DO/SYSINCLUDE to take a QuotedString argument. This allows for filenames with spaces in them. 2024-12-13 10:38:34 -05:00
19 changed files with 171 additions and 103 deletions
+17 -4
View File
@@ -1,10 +1,15 @@
CHANGES TO REMIND CHANGES TO REMIND
* VERSION 5.2 Patch 0 - ????-??=?? * VERSION 5.2 Patch 0 - 2024-12-16
- MAJOR NEW FEATURE: remind: Add the TRANSLATE command, the _() - MAJOR NEW FEATURE: remind: Add the TRANSLATE command, the _()
built-in function and the %(...) substitution sequence. These allow built-in function and the %(...) substitution sequence. These allow
you to localize your reminder files more easily. you to localize your reminder files more easily. The translation table
is also made available to back-ends like rem2pdf and tkremind,
which they can use as they see fit.
- MINOR FEATURE: tkremind, rem2html: Localize the names of the moon
phases.
- MAJOR CHANGE: remind: Remind used to support compile-time localization - MAJOR CHANGE: remind: Remind used to support compile-time localization
into different languages (French, English, etc.) That compile-time into different languages (French, English, etc.) That compile-time
@@ -27,6 +32,10 @@ CHANGES TO REMIND
INCLUDE [$SysInclude]/foo/bar.rem INCLUDE [$SysInclude]/foo/bar.rem
- MINOR IMPROVEMENT: Allow INCLUDE, DO and SYSINCLUDE to include files with
spaces in their names; in this case, you have to put the filename inside
double-quotes.
- IMPROVEMENT: remind: Refuse to open subdirectories named "*.rem" - IMPROVEMENT: remind: Refuse to open subdirectories named "*.rem"
under a top-level directory rather than trying and failing with a under a top-level directory rather than trying and failing with a
confusing error. confusing error.
@@ -43,8 +52,12 @@ CHANGES TO REMIND
- MINOR FIXES: remind: Fix typos in comments; use memcpy to copy OMIT - MINOR FIXES: remind: Fix typos in comments; use memcpy to copy OMIT
contexts internally. contexts internally.
- BUG FIX: Actually allow the documented 9 levels of INCLUDE rather than - BUG FIX: remind: Actually allow the documented 9 levels of INCLUDE
8. rather than 8.
- BUG FIX: remind: If an INCLUDE statement failed inside an IF statement,
Remind would print spurious errors about unmatched IF/ENDIF. This has
been fixed.
* VERSION 5.1 Patch 1 - 2024-11-18 * VERSION 5.1 Patch 1 - 2024-11-18
+9 -10
View File
@@ -1927,19 +1927,18 @@ commands.
.SH THE DO, INCLUDE AND SYSINCLUDE COMMANDS .SH THE DO, INCLUDE AND SYSINCLUDE COMMANDS
.PP .PP
\fBRemind\fR allows you to include other files in your reminder script, \fBRemind\fR allows you to include other files in your reminder script,
similar to the C preprocessor #include directive. For example, your similar to the C preprocessor #include directive. For example, you
system administrator may maintain a file of holidays or system-wide might organize different reminders into different files like this:
reminders. You can include these in your reminder script as follows:
.PP .PP
.nf .nf
INCLUDE /usr/share/remind/holidays INCLUDE holidays.rem
INCLUDE /usr/share/remind/reminders INCLUDE birthdays.rem
INCLUDE "quote files with spaces.rem"
.fi .fi
.PP .PP
(The actual pathnames vary from system to system - ask your system \fBINCLUDE\fR files can be nested up to a depth of 8. As shown above, if a
administrator.) filename has spaces in it (not recommended!) you can use double-quotes
.PP around the filename.
\fBINCLUDE\fR files can be nested up to a depth of 8.
.PP .PP
If you specify a filename of "-" in the \fBINCLUDE\fR command, \fBRemind\fR If you specify a filename of "-" in the \fBINCLUDE\fR command, \fBRemind\fR
will begin reading from standard input. will begin reading from standard input.
@@ -1983,7 +1982,7 @@ symbolic links to files.
.PP .PP
The \fBSYSINCLUDE\fR command is similar to \fBDO\fR, but it looks for The \fBSYSINCLUDE\fR command is similar to \fBDO\fR, but it looks for
relative pathnames under the system directory containing standard reminder relative pathnames under the system directory containing standard reminder
scripts. For thie version of \fBRemind\fR, the system directory is scripts. For this version of \fBRemind\fR, the system directory is
"@prefix@/share/remind". "@prefix@/share/remind".
.PP .PP
.SH THE RUN COMMAND .SH THE RUN COMMAND
+2 -2
View File
@@ -1272,7 +1272,7 @@ static void PrintLeft(char const *s, int width, char pad)
buf = calloc(len+1, sizeof(wchar_t)); buf = calloc(len+1, sizeof(wchar_t));
if (!buf) { if (!buf) {
/* Uh-oh... cannot recover */ /* Uh-oh... cannot recover */
fprintf(stderr, "%s\n", GetErr(E_NO_MEM)); fprintf(ErrFp, "%s\n", GetErr(E_NO_MEM));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
@@ -1357,7 +1357,7 @@ static void PrintCentered(char const *s, int width, char *pad)
buf = calloc(len+1, sizeof(wchar_t)); buf = calloc(len+1, sizeof(wchar_t));
if (!buf) { if (!buf) {
/* Uh-oh... cannot recover */ /* Uh-oh... cannot recover */
fprintf(stderr, "%s\n", GetErr(E_NO_MEM)); fprintf(ErrFp, "%s\n", GetErr(E_NO_MEM));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
+3 -7
View File
@@ -167,17 +167,13 @@ InitDedupeTable(void)
if (hash_table_init(&DedupeTable, if (hash_table_init(&DedupeTable,
offsetof(DedupeEntry, link), offsetof(DedupeEntry, link),
DedupeHashFunc, CompareDedupes) < 0) { DedupeHashFunc, CompareDedupes) < 0) {
fprintf(stderr, "Unable to initialize function hash table: Out of memory. Exiting.\n"); fprintf(ErrFp, "Unable to initialize function hash table: Out of memory. Exiting.\n");
exit(1); exit(1);
} }
} }
void void
get_dedupe_hash_stats(int *total, int *maxlen, double *avglen) dump_dedupe_hash_stats(void)
{ {
struct hash_table_stats s; hash_table_dump_stats(&DedupeTable, ErrFp);
hash_table_get_stats(&DedupeTable, &s);
*total = s.num_entries;
*maxlen = s.max_len;
*avglen = s.avg_len;
} }
+4 -4
View File
@@ -3088,10 +3088,10 @@ int DoCoerce(char type, Value *v)
/***************************************************************/ /***************************************************************/
void print_expr_nodes_stats(void) void print_expr_nodes_stats(void)
{ {
fprintf(stderr, " Expression nodes allocated: %d\n", ExprNodesAllocated); fprintf(ErrFp, " Expression nodes allocated: %d\n", ExprNodesAllocated);
fprintf(stderr, "Expression nodes high-water: %d\n", ExprNodesHighWater); fprintf(ErrFp, "Expression nodes high-water: %d\n", ExprNodesHighWater);
fprintf(stderr, " Expression nodes leaked: %d\n", ExprNodesUsed); fprintf(ErrFp, " Expression nodes leaked: %d\n", ExprNodesUsed);
fprintf(stderr, " Parse level high-water: %d\n", parse_level_high_water); fprintf(ErrFp, " Parse level high-water: %d\n", parse_level_high_water);
} }
/* Return 1 if a value is "true" for its type, 0 if "false" */ /* Return 1 if a value is "true" for its type, 0 if "false" */
+1 -1
View File
@@ -608,7 +608,7 @@ int DoInclude(ParsePtr p, enum TokTypes tok)
DBufInit(&buf); DBufInit(&buf);
DBufInit(&fullname); DBufInit(&fullname);
DBufInit(&path); DBufInit(&path);
if ( (r=ParseToken(p, &buf)) ) return r; if ( (r=ParseTokenOrQuotedString(p, &buf)) ) return r;
e = VerifyEoln(p); e = VerifyEoln(p);
if (e) Eprint("%s", GetErr(e)); if (e) Eprint("%s", GetErr(e));
+3 -3
View File
@@ -3265,11 +3265,11 @@ static int setenv(char const *varname, char const *val, int overwrite)
{ {
static char tzbuf[256]; static char tzbuf[256];
if (strcmp(varname, "TZ")) { if (strcmp(varname, "TZ")) {
fprintf(stderr, "built-in setenv can only be used with TZ\n"); fprintf(ErrFp, "built-in setenv can only be used with TZ\n");
abort(); abort();
} }
if (!overwrite) { if (!overwrite) {
fprintf(stderr, "built-in setenv must have overwrite=1\n"); fprintf(ErrFp, "built-in setenv must have overwrite=1\n");
abort(); abort();
} }
@@ -3287,7 +3287,7 @@ static void unsetenv(char const *varname)
{ {
static char tzbuf[8]; static char tzbuf[8];
if (strcmp(varname, "TZ")) { if (strcmp(varname, "TZ")) {
fprintf(stderr, "built-in unsetenv can only be used with TZ\n"); fprintf(ErrFp, "built-in unsetenv can only be used with TZ\n");
abort(); abort();
} }
sprintf(tzbuf, "%s", varname); sprintf(tzbuf, "%s", varname);
+8 -1
View File
@@ -63,7 +63,7 @@
* These are used as choices for the number of hash buckets in the table * These are used as choices for the number of hash buckets in the table
*/ */
static size_t bucket_choices[] = { static size_t bucket_choices[] = {
17, 37, 79, 163, 331, 673, 1361, 2729, 5471, 10949, 21911, 43853, 87719, 7, 17, 37, 79, 163, 331, 673, 1361, 2729, 5471, 10949, 21911, 43853, 87719,
175447, 350899, 701819, 1403641, 2807303, 5614657, 11229331, 22458671, 175447, 350899, 701819, 1403641, 2807303, 5614657, 11229331, 22458671,
44917381, 89834777, 179669557, 359339171, 718678369, 1437356741 }; 44917381, 89834777, 179669557, 359339171, 718678369, 1437356741 };
@@ -108,6 +108,8 @@ hash_table_init(hash_table *t,
t->hashfunc = hashfunc; t->hashfunc = hashfunc;
t->compare = compare; t->compare = compare;
t->buckets = malloc(sizeof(void *) * bucket_choices[0]); t->buckets = malloc(sizeof(void *) * bucket_choices[0]);
t->num_growths = 0;
t->num_shrinks = 0;
if (!t->buckets) { if (!t->buckets) {
return -1; return -1;
} }
@@ -216,6 +218,11 @@ hash_table_resize(hash_table *t, int dir)
/* Out of memory... just don't resize? */ /* Out of memory... just don't resize? */
return 0; return 0;
} }
if (dir == 1) {
t->num_growths++;
} else {
t->num_shrinks++;
}
for (size_t j=0; j<num_new_buckets; j++) { for (size_t j=0; j<num_new_buckets; j++) {
new_buckets[j] = NULL; new_buckets[j] = NULL;
} }
+4
View File
@@ -29,6 +29,8 @@ struct hash_link {
*/ */
typedef struct { typedef struct {
unsigned int bucket_choice_index; /**< Index into array of possible bucket counts */ unsigned int bucket_choice_index; /**< Index into array of possible bucket counts */
size_t num_growths; /**< How many times have we grown the hash table? */
size_t num_shrinks; /**< How many times have we grown the hash table? */
size_t num_entries; /**< Number of entries in the hash table */ size_t num_entries; /**< Number of entries in the hash table */
size_t hash_link_offset; /**< Offset of the struct hash_link in the container */ size_t hash_link_offset; /**< Offset of the struct hash_link in the container */
void **buckets; /**< Array of buckets */ void **buckets; /**< Array of buckets */
@@ -45,6 +47,8 @@ struct hash_table_stats {
size_t num_nonempty_buckets; /**< Number of non-emptry buckets */ size_t num_nonempty_buckets; /**< Number of non-emptry buckets */
size_t max_len; /**< Length of longest chain in the hash table */ size_t max_len; /**< Length of longest chain in the hash table */
size_t min_len; /**< Length of the shortest chain in the hash table */ size_t min_len; /**< Length of the shortest chain in the hash table */
size_t num_growths; /**< How many times have we grown the hash table? */
size_t num_shrinks; /**< How many times have we grown the hash table? */
double avg_len; /**< Average chain length */ double avg_len; /**< Average chain length */
double avg_nonempty_len; /**< Average chain length of non-empty bucket */ double avg_nonempty_len; /**< Average chain length of non-empty bucket */
double stddev; /**< Standard deviation of chain lengths */ double stddev; /**< Standard deviation of chain lengths */
+5 -2
View File
@@ -33,14 +33,15 @@ hash_table_dump_stats(hash_table *t, FILE *fp)
{ {
struct hash_table_stats stat; struct hash_table_stats stat;
hash_table_get_stats(t, &stat); hash_table_get_stats(t, &stat);
fprintf(fp, "#Entries: %lu\n#Buckets: %lu\n#Non-empty Buckets: %lu\n", fprintf(fp, " Entries: %lu; Buckets: %lu; Non-empty Buckets: %lu\n",
(unsigned long) stat.num_entries, (unsigned long) stat.num_entries,
(unsigned long) stat.num_buckets, (unsigned long) stat.num_buckets,
(unsigned long) stat.num_nonempty_buckets); (unsigned long) stat.num_nonempty_buckets);
fprintf(fp, "Max len: %lu\nMin len: %lu\nAvg len: %.4f\nStd dev: %.4f\nAvg nonempty len: %.4f\n", fprintf(fp, " Maxlen: %lu; Minlen: %lu; Avglen: %.3f; Stddev: %.3f; Avg nonempty len: %.3f\n",
(unsigned long) stat.max_len, (unsigned long) stat.max_len,
(unsigned long) stat.min_len, (unsigned long) stat.min_len,
stat.avg_len, stat.stddev, stat.avg_nonempty_len); stat.avg_len, stat.stddev, stat.avg_nonempty_len);
fprintf(fp, " Growths: %lu; Shrinks: %lu\n", (unsigned long) stat.num_growths, (unsigned long) stat.num_shrinks);
} }
/** /**
@@ -67,6 +68,8 @@ hash_table_get_stats(hash_table *t, struct hash_table_stats *stat)
stat->stddev = 0.0; stat->stddev = 0.0;
stat->num_nonempty_buckets = 0; stat->num_nonempty_buckets = 0;
stat->avg_nonempty_len = 0.0; stat->avg_nonempty_len = 0.0;
stat->num_growths = t->num_growths;
stat->num_shrinks = t->num_shrinks;
double sum = 0.0; double sum = 0.0;
double sumsq = 0.0; double sumsq = 0.0;
+5 -5
View File
@@ -149,7 +149,7 @@ static char const *DefaultFilename(void)
s = getenv("HOME"); s = getenv("HOME");
if (!s) { if (!s) {
fprintf(stderr, "HOME environment variable not set. Unable to determine reminder file.\n"); fprintf(ErrFp, "HOME environment variable not set. Unable to determine reminder file.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
DBufPuts(&default_filename_buf, s); DBufPuts(&default_filename_buf, s);
@@ -237,7 +237,7 @@ void InitRemind(int argc, char const *argv[])
InvokedAsRem = 1; InvokedAsRem = 1;
} }
} else { } else {
fprintf(stderr, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n"); fprintf(ErrFp, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -577,7 +577,7 @@ void InitRemind(int argc, char const *argv[])
/* -wt means get width from /dev/tty */ /* -wt means get width from /dev/tty */
ttyfd = open("/dev/tty", O_RDONLY); ttyfd = open("/dev/tty", O_RDONLY);
if (ttyfd < 0) { if (ttyfd < 0) {
fprintf(stderr, "%s: `-wt': Cannot open /dev/tty: %s\n", fprintf(ErrFp, "%s: `-wt': Cannot open /dev/tty: %s\n",
argv[0], strerror(errno)); argv[0], strerror(errno));
} else { } else {
InitCalWidthAndFormWidth(ttyfd); InitCalWidthAndFormWidth(ttyfd);
@@ -728,7 +728,7 @@ void InitRemind(int argc, char const *argv[])
default: default:
if (tok.type == T_Illegal && tok.val < 0) { if (tok.type == T_Illegal && tok.val < 0) {
fprintf(stderr, "%s: `%s'\n", GetErr(-tok.val), arg); fprintf(ErrFp, "%s: `%s'\n", GetErr(-tok.val), arg);
Usage(); Usage();
} }
Usage(); Usage();
@@ -1018,7 +1018,7 @@ AddTrustedUser(char const *username)
{ {
struct passwd *pwent; struct passwd *pwent;
if (NumTrustedUsers >= MAX_TRUSTED_USERS) { if (NumTrustedUsers >= MAX_TRUSTED_USERS) {
fprintf(stderr, "Too many trusted users (%d max)\n", fprintf(ErrFp, "Too many trusted users (%d max)\n",
MAX_TRUSTED_USERS); MAX_TRUSTED_USERS);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
+35 -15
View File
@@ -60,19 +60,21 @@ exitfunc(void)
/* Kill any execution-time-limiter process */ /* Kill any execution-time-limiter process */
unlimit_execution_time(); unlimit_execution_time();
int maxlen, total;
double avglen;
if (DebugFlag & DB_PARSE_EXPR) { if (DebugFlag & DB_PARSE_EXPR) {
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(ErrFp);
get_var_hash_stats(&total, &maxlen, &avglen); fprintf(ErrFp, "Variable hash table statistics:\n");
fprintf(stderr, " Var hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen); dump_var_hash_stats();
get_userfunc_hash_stats(&total, &maxlen, &avglen);
fprintf(stderr, " Func hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen); fprintf(ErrFp, "Function hash table statistics:\n");
get_dedupe_hash_stats(&total, &maxlen, &avglen); dump_userfunc_hash_stats();
fprintf(stderr, "Dedup hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen);
get_translation_hash_stats(&total, &maxlen, &avglen); fprintf(ErrFp, "Dedupe hash table statistics:\n");
fprintf(stderr, "Trans hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen); dump_dedupe_hash_stats();
fprintf(ErrFp, "Translation hash table statistics:\n");
dump_translation_hash_stats();
UnsetAllUserFuncs(); UnsetAllUserFuncs();
print_expr_nodes_stats(); print_expr_nodes_stats();
} }
@@ -128,7 +130,7 @@ int main(int argc, char *argv[])
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART; act.sa_flags = SA_RESTART;
if (sigaction(SIGALRM, &act, NULL) < 0) { if (sigaction(SIGALRM, &act, NULL) < 0) {
fprintf(stderr, "%s: sigaction() failed: %s\n", fprintf(ErrFp, "%s: sigaction() failed: %s\n",
argv[0], strerror(errno)); argv[0], strerror(errno));
exit(1); exit(1);
} }
@@ -137,7 +139,7 @@ int main(int argc, char *argv[])
act.sa_flags = SA_RESTART; act.sa_flags = SA_RESTART;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
if (sigaction(SIGXCPU, &act, NULL) < 0) { if (sigaction(SIGXCPU, &act, NULL) < 0) {
fprintf(stderr, "%s: sigaction() failed: %s\n", fprintf(ErrFp, "%s: sigaction() failed: %s\n",
argv[0], strerror(errno)); argv[0], strerror(errno));
exit(1); exit(1);
} }
@@ -600,6 +602,24 @@ int ParseNonSpaceChar(ParsePtr p, int *err, int peek)
return ch; return ch;
} }
/***************************************************************/
/* */
/* ParseTokenOrQuotedString */
/* */
/* Parse either a token or a double-quote-delimited string. */
/* */
/***************************************************************/
int ParseTokenOrQuotedString(ParsePtr p, DynamicBuffer *dbuf)
{
int c, err;
c = ParseNonSpaceChar(p, &err, 1);
if (err) return err;
if (c != '"') {
return ParseToken(p, dbuf);
}
return ParseQuotedString(p, dbuf);
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* ParseQuotedString */ /* ParseQuotedString */
@@ -1980,7 +2000,7 @@ get_day_name(int wkday)
if (wkday < 0 || wkday > 6) { if (wkday < 0 || wkday > 6) {
return "INVALID_WKDAY"; return "INVALID_WKDAY";
} }
return t(DayName[wkday]); return tr(DayName[wkday]);
} }
char const * char const *
@@ -1989,7 +2009,7 @@ get_month_name(int mon)
if (mon < 0 || mon > 11) { if (mon < 0 || mon > 11) {
return "INVALID_MON"; return "INVALID_MON";
} }
return t(MonthName[mon]); return tr(MonthName[mon]);
} }
static int GetOnceDateFromFile(void) static int GetOnceDateFromFile(void)
+5 -5
View File
@@ -88,6 +88,7 @@ int JulianToGregorianOffset(int y, int m);
int ParseChar (ParsePtr p, int *err, int peek); int ParseChar (ParsePtr p, int *err, int peek);
int ParseToken (ParsePtr p, DynamicBuffer *dbuf); int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
int ParseQuotedString (ParsePtr p, DynamicBuffer *dbuf); int ParseQuotedString (ParsePtr p, DynamicBuffer *dbuf);
int ParseTokenOrQuotedString (ParsePtr p, DynamicBuffer *dbuf);
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf); int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
expr_node * ParseExpr(ParsePtr p, int *r); expr_node * ParseExpr(ParsePtr p, int *r);
void print_expr_nodes_stats(void); void print_expr_nodes_stats(void);
@@ -255,10 +256,10 @@ void print_builtinfunc_tokens(void);
void print_remind_tokens(void); void print_remind_tokens(void);
/* Stats for -ds output */ /* Stats for -ds output */
void get_var_hash_stats(int *total, int *maxlen, double *avglen); void dump_var_hash_stats(void);
void get_userfunc_hash_stats(int *total, int *maxlen, double *avglen); void dump_userfunc_hash_stats(void);
void get_dedupe_hash_stats(int *total, int *maxlen, double *avglen); void dump_dedupe_hash_stats(void);
void get_translation_hash_stats(int *total, int *maxlen, double *avglen); void dump_translation_hash_stats(void);
/* Dedupe code */ /* Dedupe code */
int ShouldDedupe(int trigger_date, int trigger_time, char const *body); int ShouldDedupe(int trigger_date, int trigger_time, char const *body);
@@ -271,6 +272,5 @@ void InitTranslationTable(void);
char const *GetTranslatedString(char const *orig); char const *GetTranslatedString(char const *orig);
int GetTranslatedStringTryingVariants(char const *orig, DynamicBuffer *out); int GetTranslatedStringTryingVariants(char const *orig, DynamicBuffer *out);
char const *GetErr(int r); char const *GetErr(int r);
char const *t(char const *s);
char const *tr(char const *s); char const *tr(char const *s);
void print_escaped_string(FILE *fp, char const *s); void print_escaped_string(FILE *fp, char const *s);
+4 -14
View File
@@ -202,7 +202,7 @@ InitTranslationTable(void)
{ {
if (hash_table_init(&TranslationTable, offsetof(XlateItem, link), if (hash_table_init(&TranslationTable, offsetof(XlateItem, link),
HashXlateItem, CompareXlateItems) < 0) { HashXlateItem, CompareXlateItems) < 0) {
fprintf(stderr, "Unable to initialize translation hash table: Out of memory. Exiting.\n"); fprintf(ErrFp, "Unable to initialize translation hash table: Out of memory. Exiting.\n");
exit(1); exit(1);
} }
InsertTranslation("LANGID", "en"); InsertTranslation("LANGID", "en");
@@ -313,7 +313,7 @@ GetTranslatedStringTryingVariants(char const *orig, DynamicBuffer *out)
return 0; return 0;
} }
char const *t(char const *orig) char const *tr(char const *orig)
{ {
char const *n = GetTranslatedString(orig); char const *n = GetTranslatedString(orig);
if (n) { if (n) {
@@ -322,12 +322,6 @@ char const *t(char const *orig)
return orig; return orig;
} }
/* If another "t" is in scope... */
char const *tr(char const *orig)
{
return t(orig);
}
int int
DoTranslate(ParsePtr p) DoTranslate(ParsePtr p)
{ {
@@ -392,12 +386,8 @@ DoTranslate(ParsePtr p)
} }
void void
get_translation_hash_stats(int *total, int *maxlen, double *avglen) dump_translation_hash_stats(void)
{ {
struct hash_table_stats s; hash_table_dump_stats(&TranslationTable, ErrFp);
hash_table_get_stats(&TranslationTable, &s);
*total = s.num_entries;
*maxlen = s.max_len;
*avglen = s.avg_len;
} }
+3 -7
View File
@@ -56,7 +56,7 @@ InitUserFunctions(void)
offsetof(UserFunc, link), offsetof(UserFunc, link),
HashUserFunc, HashUserFunc,
CompareUserFuncs) < 0) { CompareUserFuncs) < 0) {
fprintf(stderr, "Unable to initialize function hash table: Out of memory. Exiting.\n"); fprintf(ErrFp, "Unable to initialize function hash table: Out of memory. Exiting.\n");
exit(1); exit(1);
} }
} }
@@ -506,12 +506,8 @@ RenameUserFunc(char const *oldname, char const *newname)
} }
void void
get_userfunc_hash_stats(int *total, int *maxlen, double *avglen) dump_userfunc_hash_stats(void)
{ {
struct hash_table_stats s; hash_table_dump_stats(&FuncHash, ErrFp);
hash_table_get_stats(&FuncHash, &s);
*total = s.num_entries;
*maxlen = s.max_len;
*avglen = s.avg_len;
} }
+5 -9
View File
@@ -56,7 +56,7 @@ InitVars(void)
{ {
if (hash_table_init(&VHashTbl, offsetof(Var, link), if (hash_table_init(&VHashTbl, offsetof(Var, link),
VarHashFunc, VarCompareFunc) < 0) { VarHashFunc, VarCompareFunc) < 0) {
fprintf(stderr, "Unable to initialize variable hash table: Out of memory. Exiting.\n"); fprintf(ErrFp, "Unable to initialize variable hash table: Out of memory. Exiting.\n");
exit(1); exit(1);
} }
} }
@@ -723,7 +723,7 @@ int DoDump(ParsePtr p)
/* */ /* */
/* DumpVarTable */ /* DumpVarTable */
/* */ /* */
/* Dump the variable table to stderr. */ /* Dump the variable table to ErrFp. */
/* */ /* */
/***************************************************************/ /***************************************************************/
void DumpVarTable(void) void DumpVarTable(void)
@@ -968,7 +968,7 @@ static int SetTranslatableVariable(SysVar *v, Value *value)
static int GetTranslatableVariable(SysVar *v, Value *value) static int GetTranslatableVariable(SysVar *v, Value *value)
{ {
char const *translated = t((char const *) v->value); char const *translated = tr((char const *) v->value);
if (translated) { if (translated) {
value->v.str = StrDup(translated); value->v.str = StrDup(translated);
} else { } else {
@@ -1249,11 +1249,7 @@ print_sysvar_tokens(void)
} }
void void
get_var_hash_stats(int *total, int *maxlen, double *avglen) dump_var_hash_stats(void)
{ {
struct hash_table_stats s; hash_table_dump_stats(&VHashTbl, ErrFp);
hash_table_get_stats(&VHashTbl, &s);
*total = s.num_entries;
*maxlen = s.max_len;
*avglen = s.avg_len;
} }
+55 -14
View File
@@ -16127,8 +16127,8 @@ TRANSLATE "January" "translated-January"
TRANSLATE "Tuesday" "translated-Tuesday" TRANSLATE "Tuesday" "translated-Tuesday"
TRANSLATE "November" "translated-November" TRANSLATE "November" "translated-November"
TRANSLATE "tomorrow" "translated-Tomorrow" TRANSLATE "tomorrow" "translated-Tomorrow"
TRANSLATE "today" "translated-Today"
TRANSLATE "is" "translated-Is" TRANSLATE "is" "translated-Is"
TRANSLATE "today" "translated-Today"
TRANSLATE "from now" "translated-Fromnow" TRANSLATE "from now" "translated-Fromnow"
TRANSLATE "Friday" "translated-Friday" TRANSLATE "Friday" "translated-Friday"
TRANSLATE "am" "translated-Am" TRANSLATE "am" "translated-Am"
@@ -16139,8 +16139,8 @@ TRANSLATE "pm" "translated-Pm"
TRANSLATE "August" "translated-August" TRANSLATE "August" "translated-August"
TRANSLATE "May" "translated-May" TRANSLATE "May" "translated-May"
TRANSLATE "February" "translated-February" TRANSLATE "February" "translated-February"
TRANSLATE "on" "translated-On"
TRANSLATE "now" "translated-Now" TRANSLATE "now" "translated-Now"
TRANSLATE "on" "translated-On"
$Ago is otherway-Ago $Ago is otherway-Ago
$Am is otherway-Am $Am is otherway-Am
$And is otherway-And $And is otherway-And
@@ -16232,11 +16232,28 @@ IF 1
../tests/test.rem(1435): Can't open file: /non/existent/file/should/not/work/wookie ../tests/test.rem(1435): Can't open file: /non/existent/file/should/not/work/wookie
ENDIF ENDIF
do "with space.rem"
REM MSG D'oh, a file whose name has spaces! [filename()]
D'oh, a file whose name has spaces! ../tests/with space.rem
DEBUG -e DEBUG -e
Var hash: total = 100141; maxlen = 5; avglen = 1.142 Variable hash table statistics:
Func hash: total = 100016; maxlen = 5; avglen = 1.140 Entries: 100141; Buckets: 87719; Non-empty Buckets: 66299
Dedup hash: total = 10000; maxlen = 7; avglen = 1.828 Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510
Trans hash: total = 1; maxlen = 1; avglen = 0.059 Growths: 13; Shrinks: 0
Function hash table statistics:
Entries: 100016; Buckets: 87719; Non-empty Buckets: 63572
Maxlen: 5; Minlen: 0; Avglen: 1.140; Stddev: 0.934; Avg nonempty len: 1.573
Growths: 13; Shrinks: 0
Dedupe hash table statistics:
Entries: 10000; Buckets: 5471; Non-empty Buckets: 4752
Maxlen: 7; Minlen: 0; Avglen: 1.828; Stddev: 1.302; Avg nonempty len: 2.104
Growths: 9; Shrinks: 0
Translation hash table statistics:
Entries: 1; Buckets: 7; Non-empty Buckets: 1
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
Growths: 0; Shrinks: 0
Expression nodes allocated: 300096 Expression nodes allocated: 300096
Expression nodes high-water: 300073 Expression nodes high-water: 300073
Expression nodes leaked: 0 Expression nodes leaked: 0
@@ -23702,10 +23719,22 @@ Parsed expression: isany("foo", 1 + 1, 2:00 + 1, '2021-01-01' + 1, '2021-01-01@1
"f" + "oo" => "foo" "f" + "oo" => "foo"
isany("foo", 2, 02:01, 2021-01-02, 2021-01-01@14:01, "foo", ?) => 1 isany("foo", 2, 02:01, 2021-01-02, 2021-01-01@14:01, "foo", ?) => 1
No reminders. No reminders.
Var hash: total = 1; maxlen = 1; avglen = 0.059 Variable hash table statistics:
Func hash: total = 0; maxlen = 0; avglen = 0.000 Entries: 1; Buckets: 7; Non-empty Buckets: 1
Dedup hash: total = 0; maxlen = 0; avglen = 0.000 Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
Trans hash: total = 1; maxlen = 1; avglen = 0.059 Growths: 0; Shrinks: 0
Function hash table statistics:
Entries: 0; Buckets: 7; Non-empty Buckets: 0
Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000
Growths: 0; Shrinks: 0
Dedupe hash table statistics:
Entries: 0; Buckets: 7; Non-empty Buckets: 0
Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000
Growths: 0; Shrinks: 0
Translation hash table statistics:
Entries: 1; Buckets: 7; Non-empty Buckets: 1
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
Growths: 0; Shrinks: 0
Expression nodes allocated: 512 Expression nodes allocated: 512
Expression nodes high-water: 499 Expression nodes high-water: 499
Expression nodes leaked: 0 Expression nodes leaked: 0
@@ -24229,10 +24258,22 @@ $Uy
$Was $Was
$Wednesday $Wednesday
No reminders. No reminders.
Var hash: total = 1; maxlen = 1; avglen = 0.059 Variable hash table statistics:
Func hash: total = 1; maxlen = 1; avglen = 0.059 Entries: 1; Buckets: 7; Non-empty Buckets: 1
Dedup hash: total = 0; maxlen = 0; avglen = 0.000 Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
Trans hash: total = 2; maxlen = 1; avglen = 0.118 Growths: 13; Shrinks: 13
Function hash table statistics:
Entries: 1; Buckets: 7; Non-empty Buckets: 1
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
Growths: 13; Shrinks: 13
Dedupe hash table statistics:
Entries: 0; Buckets: 7; Non-empty Buckets: 0
Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000
Growths: 0; Shrinks: 0
Translation hash table statistics:
Entries: 2; Buckets: 7; Non-empty Buckets: 1
Maxlen: 2; Minlen: 0; Avglen: 0.286; Stddev: 0.700; Avg nonempty len: 2.000
Growths: 13; Shrinks: 13
Expression nodes allocated: 300032 Expression nodes allocated: 300032
Expression nodes high-water: 300000 Expression nodes high-water: 300000
Expression nodes leaked: 0 Expression nodes leaked: 0
+2
View File
@@ -1435,6 +1435,8 @@ IF 1
INCLUDE /non/existent/file/should/not/work/wookie INCLUDE /non/existent/file/should/not/work/wookie
ENDIF ENDIF
do "with space.rem"
DEBUG -e DEBUG -e
# Output expression-node stats # Output expression-node stats
+1
View File
@@ -0,0 +1 @@
REM MSG D'oh, a file whose name has spaces! [filename()]