diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-06-01 21:41:11 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-06-01 22:01:57 +0300 |
commit | 58cc7c8f6bd1956a47f56c3aba1be8a417916064 (patch) | |
tree | 04dfcd03e11372075aaf1623a5c59ab344617a8d | |
parent | be0acbf50cdf76521a549a8495052c9ab88ed553 (diff) | |
download | mailutils-58cc7c8f6bd1956a47f56c3aba1be8a417916064.tar.gz mailutils-58cc7c8f6bd1956a47f56c3aba1be8a417916064.tar.bz2 |
Revise the mime.types lexer; provide the testsuite
* am/testsuite.m4: New file.
* configure.ac: Use the MU_CONFIG_TESTSUITE macro.
* mimeview/Makefile.am (SUBDIRS): Add tests
* mimeview/mimetypes.l: Rewrite in three exclusive states.
* mimeview/mimetypes.y: Simplify grammar.
* mimeview/mimeview.c: New option --identify (-i).
* mimeview/mimeview.h: Update.
* mimeview/tests/Makefile.am: New file.
* mimeview/tests/atlocal.in: New file.
* mimeview/tests/bf.c: New file.
* mimeview/tests/testsuite.at: New file.
* README: Update.
* doc/texinfo/programs.texi
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | am/testsuite.m4 | 5 | ||||
-rw-r--r-- | configure.ac | 48 | ||||
-rw-r--r-- | doc/texinfo/programs.texi | 4 | ||||
-rw-r--r-- | mimeview/Makefile.am | 2 | ||||
-rw-r--r-- | mimeview/mimetypes.l | 190 | ||||
-rw-r--r-- | mimeview/mimetypes.y | 91 | ||||
-rw-r--r-- | mimeview/mimeview.c | 29 | ||||
-rw-r--r-- | mimeview/mimeview.h | 13 | ||||
-rw-r--r-- | mimeview/tests/.gitignore | 7 | ||||
-rw-r--r-- | mimeview/tests/Makefile.am | 68 | ||||
-rw-r--r-- | mimeview/tests/atlocal.in | 5 | ||||
-rw-r--r-- | mimeview/tests/bf.c | 200 | ||||
-rw-r--r-- | mimeview/tests/testsuite.at | 200 |
14 files changed, 693 insertions, 174 deletions
@@ -1,4 +1,4 @@ -GNU mailutils NEWS -- history of user-visible changes. 2017-05-31 +GNU mailutils NEWS -- history of user-visible changes. 2017-06-01 Copyright (C) 2002-2017 Free Software Foundation, Inc. See the end of file for copying conditions. @@ -145,6 +145,9 @@ New option '--lint' (short '-t') instructs the tool to check the syntax of the mime.types file and exit, ignoring any surplus command line arguments. +New option '-i' ('--identify') identifies and prints the MIME type for +each input file, but not starts viewer. + Added support for priority and regex functions. Debugging considerably improved. diff --git a/am/testsuite.m4 b/am/testsuite.m4 new file mode 100644 index 000000000..f61df4a08 --- /dev/null +++ b/am/testsuite.m4 @@ -0,0 +1,5 @@ +# Initialize the (autotest) test suite. +AC_DEFUN([MU_CONFIG_TESTSUITE], +[AC_CONFIG_TESTDIR([$1/tests]) +AC_CONFIG_FILES([$1/tests/Makefile $1/tests/atlocal]) +]) diff --git a/configure.ac b/configure.ac index 8288a4d9a..3f8418873 100644 --- a/configure.ac +++ b/configure.ac @@ -1324,40 +1324,22 @@ test -z "$server_list" && server_list=" [NONE]" test -z "$client_list" && client_list=" [NONE]" # Initialize the (autotest) test suite. -AC_CONFIG_TESTDIR(libmailutils/tests) + AC_CONFIG_TESTDIR(testsuite) -AC_CONFIG_TESTDIR(frm/tests) -AC_CONFIG_TESTDIR(maidag/tests) -AC_CONFIG_TESTDIR(mail/tests) -AC_CONFIG_TESTDIR(messages/tests) -AC_CONFIG_TESTDIR(readmsg/tests) -AC_CONFIG_TESTDIR(sieve/tests) -AC_CONFIG_TESTDIR(mh/tests) -AC_CONFIG_TESTDIR(comsat/tests) -AC_CONFIG_TESTDIR(imap4d/tests) - -AC_CONFIG_FILES([libmailutils/tests/Makefile - libmailutils/tests/atlocal - testsuite/Makefile - testsuite/atlocal - comsat/tests/Makefile - comsat/tests/atlocal - frm/tests/Makefile - frm/tests/atlocal - imap4d/tests/Makefile - imap4d/tests/atlocal - maidag/tests/Makefile - maidag/tests/atlocal - mail/tests/Makefile - mail/tests/atlocal - messages/tests/Makefile - messages/tests/atlocal - readmsg/tests/Makefile - readmsg/tests/atlocal - sieve/tests/Makefile - sieve/tests/atlocal - mh/tests/Makefile - mh/tests/atlocal]) +AC_CONFIG_FILES([testsuite/Makefile testsuite/atlocal]) + +MU_CONFIG_TESTSUITE(libmailutils) +MU_CONFIG_TESTSUITE(frm) +MU_CONFIG_TESTSUITE(maidag) +MU_CONFIG_TESTSUITE(mail) +MU_CONFIG_TESTSUITE(messages) +MU_CONFIG_TESTSUITE(readmsg) +MU_CONFIG_TESTSUITE(sieve) +MU_CONFIG_TESTSUITE(mh) +MU_CONFIG_TESTSUITE(comsat) +MU_CONFIG_TESTSUITE(imap4d) +MU_CONFIG_TESTSUITE(mimeview) + AM_MISSING_PROG([AUTOM4TE], [autom4te]) dnl Make sysconfdir available to the application diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi index 954f782a3..9bcd6c363 100644 --- a/doc/texinfo/programs.texi +++ b/doc/texinfo/programs.texi @@ -7359,6 +7359,10 @@ By default @command{mimeview} behaves as if given @option{--no-interactive} option whenever its standard input is not a @asis{tty} device. +@item -i +@itemx --identify +Identifies and prints the MIME type for each input file. + @item -n @itemx --dry-run Do not do anything, just print what would be done. Implies diff --git a/mimeview/Makefile.am b/mimeview/Makefile.am index bb2bc2227..2ae80fc92 100644 --- a/mimeview/Makefile.am +++ b/mimeview/Makefile.am @@ -15,6 +15,8 @@ ## You should have received a copy of the GNU General Public License ## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. +SUBDIRS = tests + AM_CPPFLAGS = \ @MU_APP_COMMON_INCLUDES@\ -D_GNU_SOURCE=1\ diff --git a/mimeview/mimetypes.l b/mimeview/mimetypes.l index 6e74163b7..de03ea097 100644 --- a/mimeview/mimetypes.l +++ b/mimeview/mimetypes.l @@ -42,9 +42,16 @@ digit_to_number (char c) c-'a'+10); } +static struct mu_locus prev_loc; +static struct mu_locus string_beg; +static int prev_newline; + static void advance_locus (void) { + prev_loc = loc; + prev_newline = newline; + if (newline) { loc.mu_line++; @@ -54,99 +61,174 @@ advance_locus (void) loc.mu_col += yyleng; yylloc.end = loc; yylloc.end.mu_col--; - + +#if 0 + printf ("+%2d> %u:%u-%u:%u: %s\n", + yyleng, + yylloc.beg.mu_line, yylloc.beg.mu_col, + yylloc.end.mu_line, yylloc.end.mu_col, yytext); +#endif newline = yytext[yyleng-1] == '\n'; mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_LOCUS, &loc); } -#define YY_USER_ACTION advance_locus (); +static void +retreat_locus (void) +{ + loc = prev_loc; + newline = prev_newline; +} +static void +finish_string (void) +{ + mu_opool_append_char (pool, 0); + yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); + yylval.string.len--; + yylloc.end = yylloc.beg; + yylloc.end.mu_col--; + yylloc.beg = string_beg; + if (mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE5)) + { + size_t i; + mu_debug_log_begin ("string %d: ", yylval.string.len); + for (i = 0; i < yylval.string.len; i++) + if (mu_isprint (yylval.string.ptr[i])) + mu_debug_log_cont ("%c", yylval.string.ptr[i]); + else + mu_debug_log_cont ("\\%03o", yylval.string.ptr[i]); + mu_debug_log_nl (); + } +#if 0 + YY_LOCATION_PRINT (stderr, yylloc); + fprintf (stderr, ": %s\n", yylval.string.ptr); +#endif +} + +#define YY_USER_ACTION advance_locus (); %} %option nounput %option noinput -%s RULE ARGS +%x RULE ARGS ASTRING X [0-9a-fA-F] IDENT [a-zA-Z_\.][a-zA-Z0-9_\.-]* -WS [ \t]* +WS [ \t][ \t]* %% + +<INITIAL>{ /* Comments */ ^#.*\n ; - /* Tokens */ -\\\n ; -\n+ { loc.mu_line += yyleng - 1; return EOL; } -{WS} ; -<INITIAL,RULE>^[^ \t\n/]+"/"[^ \t\n]+ { +\n ; +^[^ \t\n/]+"/"[^ \t\n]+ { mu_opool_append (pool, yytext, yyleng); mu_opool_append_char (pool, 0); yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); + yylval.string.len--; BEGIN (RULE); return TYPE; } +} + +<RULE>{ +\\\n ; +\n { + BEGIN (INITIAL); + return EOL; +} +{WS} ; + + /* Operators */ +"!"|"+"|","|"("|")"|"/" return yytext[0]; + /* Special cases: && and ||. Docs don't say anything about them, but + I've found them in my mime.types file... --Sergey */ +"&&" return '+'; +"||" return ','; -<RULE>"priority"/"(" { +"priority"/"(" { return PRIORITY; } -<RULE>{IDENT}/"(" { + +{IDENT}/"(" { mu_opool_append (pool, yytext, yyleng); mu_opool_append_char (pool, 0); yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); + BEGIN (ARGS); return IDENT; -} -<RULE>{IDENT} { +} + +[a-zA-Z0-9_.-]+/[^(] { mu_opool_append (pool, yytext, yyleng); - mu_opool_append_char (pool, 0); yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); return STRING; } -<RULE,ARGS>\"[^"\n]*\" { + +. mu_error("unexpected character '%c'", yytext[0]); +} + +<ARGS>{ +"("|"," return yytext[0]; +")" { + BEGIN (RULE); + return yytext[0]; +} +{WS} mu_error ("unexpected whitespace in argument list"); +\n { + mu_error ("unexpected newline in argument list"); + BEGIN (RULE); + return EOL; +} +. { + string_beg = yylloc.beg; + retreat_locus (); + yyless (0); + BEGIN (ASTRING); +} +} + +<ASTRING>{ + /* Quoted string */ +\"[^"\n]*\" { + mu_opool_append (pool, yytext+1, yyleng-2); +} +"'"[^'\n]*"'" { mu_opool_append (pool, yytext+1, yyleng-2); - mu_opool_append_char (pool, 0); - yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); - return STRING; } -<RULE,ARGS>"<"({X}{X})+">" { + + /* Hex string */ +"<"({X}{X})+">" { int i; - for (i = 0; i < yyleng; i += 2) + for (i = 1; i < yyleng - 2; i += 2) { mu_opool_append_char (pool, digit_to_number (yytext[i])*16 + digit_to_number (yytext[i+1])); - } - yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); - return STRING; + } } -<ARGS>[^ \t<\n),<"]+/[),<"] { + + /* Unquoted character sequence */ +[^ \t\n,)<"']+/[^"'<] { mu_opool_append (pool, yytext, yyleng); - mu_opool_append_char (pool, 0); - yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); - return STRING; } -<RULE>[^ \t<\\\n)+,&]/[ \t\\\n)+,&] { + +[^ \t\n,)<"]+/< { mu_opool_append (pool, yytext, yyleng); - mu_opool_append_char (pool, 0); - yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); - return STRING; } -<ARGS>[^ \t<\\\n),]/[ \t\\\n] { + +[^ \t\n,)<"]+/["'] { mu_opool_append (pool, yytext, yyleng); - mu_opool_append_char (pool, 0); - yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); +} + +. { + retreat_locus (); + yyless (0); + BEGIN (ARGS); + finish_string (); return STRING; } - /* Special cases: && and ||. Docs don't say anything about them, but - I've found them in my mime.types file... --Sergey */ -"&&" return '+'; -"||" return ','; - /* Operators */ -<RULE>"!"|"+"|","|"("|")"|"/" return yytext[0]; -<ARGS>"," return yytext[0]; -<ARGS>")" { BEGIN (RULE); return yytext[0]; } -<*>. { - mu_error ("invalid character '%c', state %d", yytext[0], YYSTATE); - return BOGUS; } + %% int mimetypes_open (const char *name) @@ -236,21 +318,7 @@ mimetypes_malloc (size_t size) } void -lex_arglist (int enable) -{ - if (enable) - BEGIN (ARGS); - else - BEGIN (RULE); -} - -void -lex_concat (struct concat_segm *p, struct mimetypes_string *ret) +lex_reset (void) { - for (; p; p = p->next) - { - mu_opool_appendz (pool, p->val); - } - mu_opool_append_char (pool, 0); - ret->ptr = mu_opool_finish (pool, &ret->len); + BEGIN (INITIAL); } diff --git a/mimeview/mimetypes.y b/mimeview/mimetypes.y index 051aa9967..6d6bc31ed 100644 --- a/mimeview/mimetypes.y +++ b/mimeview/mimetypes.y @@ -132,12 +132,10 @@ static mu_list_t rule_list; %left ',' %left '+' -%type <string> string arg +%type <string> arg %type <list> arglist %type <node> function stmt rule maybe_rule %type <result> priority maybe_priority -%type <concat> concat; -%type <segment> simple_string %union { struct mimetypes_string string; @@ -145,8 +143,6 @@ static mu_list_t rule_list; mu_list_t list; int result; struct node *node; - struct { struct concat_segm *head, *tail; } concat; - struct concat_segm *segment; } %% @@ -176,7 +172,7 @@ rule_line: /* empty */ if (arg_list) mu_list_destroy (&arg_list); arg_list = NULL; - lex_arglist (0); + lex_reset (); } ; @@ -219,39 +215,14 @@ stmt : '!' stmt { $$ = $2; } - | string + | STRING { $$ = make_suffix_node (&$1, &@1); } | function ; -string : concat - { - lex_concat ($1.head, &$$); - } - ; - -concat : simple_string - { - $$.head = $$.tail = $1; - } - | concat simple_string - { - $$.tail->next = $2; - $$.tail = $2; - } - ; - -simple_string : STRING - { - $$ = mu_alloc (sizeof $$); - $$->next = NULL; - $$->val = $1.ptr; - } - ; - -priority : PRIORITY oparen arglist cparen +priority : PRIORITY '(' arglist ')' { size_t count = 0; struct mimetypes_string *arg; @@ -275,19 +246,7 @@ maybe_priority: /* empty */ | priority ; -oparen : '(' - { - lex_arglist (1); - } - ; - -cparen : ')' - { - lex_arglist (0); - } - ; - -function : IDENT oparen arglist cparen +function : IDENT '(' arglist ')' { struct mu_locus_range lr; lr.beg = @1.beg; @@ -312,7 +271,7 @@ arglist : arg } ; -arg : string +arg : STRING ; %% @@ -387,6 +346,9 @@ b_match (union argument *args) True if bytes are valid printable ASCII (CR, NL, TAB, BS, 32-126) */ +#define ISASCII(c) ((c) &&\ + (strchr ("\n\r\t\b",c) \ + || (32<=((unsigned) c) && ((unsigned) c)<=126))) static int b_ascii (union argument *args) { @@ -402,13 +364,13 @@ b_ascii (union argument *args) for (i = 0; i < args[1].number; i++) { - char c; + unsigned char c; size_t n; rc = mu_stream_read (mimeview_stream, &c, 1, &n); if (rc || n == 0) break; - if (!mu_isascii (c)) + if (!ISASCII (c)) return 0; } @@ -419,10 +381,8 @@ b_ascii (union argument *args) True if bytes are printable 8-bit chars (CR, NL, TAB, BS, 32-126, 128-254) */ -#define ISPRINT(c) ((c) &&\ - (strchr ("\n\r\t\b",c) \ - || (32<=(c) && (c)<=126) \ - || (128<=(c) && (c)<=254))) +#define ISPRINT(c) (ISASCII (c) \ + || (128<=((unsigned) c) && ((unsigned) c)<=254)) static int b_printable (union argument *args) { @@ -438,13 +398,13 @@ b_printable (union argument *args) for (i = 0; i < args[1].number; i++) { - char c; + unsigned char c; size_t n; rc = mu_stream_read (mimeview_stream, &c, 1, &n); if (rc || n == 0) break; - if (!ISPRINT ((unsigned)c)) + if (!ISPRINT (c)) return 0; } return 1; @@ -552,8 +512,8 @@ b_char (union argument *args) static int b_short (union argument *args) { - unsigned short val = args[1].number; - unsigned short buf; + uint16_t val = args[1].number; + uint16_t buf; return compare_bytes (args, &val, &buf, sizeof (buf)); } @@ -564,8 +524,8 @@ b_short (union argument *args) static int b_int (union argument *args) { - unsigned int val = args[1].number; - unsigned int buf; + uint32_t val = args[1].number; + uint32_t buf; return compare_bytes (args, &val, &buf, sizeof (buf)); } @@ -604,7 +564,7 @@ b_contains (union argument *args) mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read", NULL, rc); } else if (count > str->len) - for (i = 0; i < count - str->len; i++) + for (i = 0; i <= count - str->len; i++) if (buf[i] == str->ptr[0] && memcmp (buf + i, str->ptr, str->len) == 0) { free (buf); @@ -896,7 +856,16 @@ rule_cmp (const void *a, const void *b) struct rule_tab const *brule = b; if (arule->priority == brule->priority) - return mu_c_strcasecmp (arule->type, brule->type); + { + if (arule->node->type == true_node + && brule->node->type != true_node) + return 1; + else if (brule->node->type == true_node + && arule->node->type != true_node) + return -1; + else + return mu_c_strcasecmp (arule->type, brule->type); + } return arule->priority - brule->priority; } diff --git a/mimeview/mimeview.c b/mimeview/mimeview.c index 84a28adc1..e67593d14 100644 --- a/mimeview/mimeview.c +++ b/mimeview/mimeview.c @@ -33,12 +33,13 @@ static int dry_run; /* Dry run mode */ static int lint; /* Syntax check mode */ +static int identify; /* Print only the file's type */ static char *metamail; /* Name of metamail program, if requested */ static char *mimetypes_config = DEFAULT_CUPS_CONFDIR; static char *no_ask_types; /* List of MIME types for which no questions should be asked */ static int interactive = -1; -char *mimeview_file; /* Name of the file to view */ +char const *mimeview_file; /* Name of the file to view */ mu_stream_t mimeview_stream; /* The corresponding stream */ @@ -121,6 +122,10 @@ static struct mu_option mimeview_options[] = { { "lint", 't', NULL, MU_OPTION_DEFAULT, N_("test mime.types syntax and exit"), mu_c_bool, &lint }, + + { "identify", 'i', NULL, MU_OPTION_DEFAULT, + N_("identify MIME type of each file"), + mu_c_bool, &identify }, { "metamail", 0, N_("FILE"), MU_OPTION_ARG_OPTIONAL, N_("use metamail to display files"), @@ -157,7 +162,7 @@ static char *capa[] = { }; static int -open_file (char *name) +open_file (char const *name) { int rc; struct stat st; @@ -190,9 +195,18 @@ close_file () } void -display_file (const char *type) +display_file (const char *file, const char *type) { int status; + + if (identify) + { + printf ("%s: %s\n", file, type ? type : "unknown"); + return; + } + + if (!type) + return; if (metamail) { @@ -205,7 +219,7 @@ display_file (const char *type) argv[3] = "-c"; argv[4] = (char*) type; - argv[5] = mimeview_file; + argv[5] = (char*) mimeview_file; argv[6] = NULL; if (mu_debug_level_p (MU_DEBCAT_MIME, MU_DEBUG_TRACE0)) @@ -269,12 +283,11 @@ main (int argc, char **argv) while (argc--) { const char *type; - - if (open_file (*argv++)) + char const *file = *argv++; + if (open_file (file)) continue; type = get_file_type (); - if (type) - display_file (type); + display_file (file, type); close_file (); } diff --git a/mimeview/mimeview.h b/mimeview/mimeview.h index b940b0836..36f9fbfa3 100644 --- a/mimeview/mimeview.h +++ b/mimeview/mimeview.h @@ -37,24 +37,17 @@ int mimetypes_open (const char *name); void mimetypes_close (void); int mimetypes_parse (const char *name); void mimetypes_lex_init (void); -void lex_arglist (int); + +void lex_reset (void); void *mimetypes_malloc (size_t size); struct mimetypes_string *mimetypes_string_dup (struct mimetypes_string *s); const char *get_file_type (void); -extern char *mimeview_file; +extern char const *mimeview_file; extern mu_stream_t mimeview_stream; -struct concat_segm -{ - struct concat_segm *next; - char const *val; -}; - -void lex_concat (struct concat_segm *p, struct mimetypes_string *ret); - struct mu_locus_range { struct mu_locus beg; diff --git a/mimeview/tests/.gitignore b/mimeview/tests/.gitignore new file mode 100644 index 000000000..a0a8955c1 --- /dev/null +++ b/mimeview/tests/.gitignore @@ -0,0 +1,7 @@ +atconfig +atlocal +bf +package.m4 +testsuite +testsuite.dir +testsuite.log diff --git a/mimeview/tests/Makefile.am b/mimeview/tests/Makefile.am new file mode 100644 index 000000000..ae04580f6 --- /dev/null +++ b/mimeview/tests/Makefile.am @@ -0,0 +1,68 @@ +# This file is part of GNU Mailutils. +# Copyright (C) 2017 Free Software Foundation, Inc. +# +# GNU Mailutils is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or (at +# your option) any later version. +# +# GNU Mailutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. + +EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 +DISTCLEANFILES = atconfig $(check_SCRIPTS) +MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) + +## ------------ ## +## package.m4. ## +## ------------ ## + +$(srcdir)/package.m4: $(top_srcdir)/configure.ac + $(AM_V_GEN){ \ + echo '# Signature of the current package.'; \ + echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ + echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ + echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ + echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ + echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ + } >$(srcdir)/package.m4 + +## -------------------------- ## +## Non-installable programs ## +## -------------------------- ## + +noinst_PROGRAMS = bf + +## ------------ ## +## Test suite. ## +## ------------ ## + +TESTSUITE_AT = testsuite.at + +TESTSUITE = $(srcdir)/testsuite +M4=m4 + +AUTOTEST = $(AUTOM4TE) --language=autotest +$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc + $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp + $(AM_V_at)mv $@.tmp $@ + +atconfig: $(top_builddir)/config.status + cd $(top_builddir) && ./config.status tests/$@ + +clean-local: + @test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean + +check-local: atconfig atlocal $(TESTSUITE) + @$(SHELL) $(TESTSUITE) + +# Run the test suite on the *installed* tree. +#installcheck-local: +# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin + + diff --git a/mimeview/tests/atlocal.in b/mimeview/tests/atlocal.in new file mode 100644 index 000000000..8112255c5 --- /dev/null +++ b/mimeview/tests/atlocal.in @@ -0,0 +1,5 @@ +# @configure_input@ -*- shell-script -*- +# Configurable variable values for Mailutils test suite. + +PATH=@abs_builddir@:@abs_top_builddir@/mimeview:$top_srcdir:$srcdir:$PATH + diff --git a/mimeview/tests/bf.c b/mimeview/tests/bf.c new file mode 100644 index 000000000..e27561654 --- /dev/null +++ b/mimeview/tests/bf.c @@ -0,0 +1,200 @@ +/* This file is part of the GNU Mailutils testsuite. + Copyright (C) 2017 Free Software Foundation, Inc. + + GNU Mailutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Mailutils is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> +#include <assert.h> +#include <inttypes.h> + +typedef int (*ACTION) (FILE *, char *); + +int +seek_file (FILE *fp, char *arg) +{ + long off; + int whence; + + switch (arg[0]) + { + case '+': + whence = SEEK_CUR; + arg++; + break; + + case '-': + whence = SEEK_CUR; + break; + + case '$': + whence = SEEK_END; + arg++; + break; + + default: + whence = SEEK_SET; + } + + if (sscanf (arg, "%ld", &off) != 1) + { + fprintf (stderr, "bad offset: %s\n", arg); + abort (); + } + return fseek (fp, off, whence); +} + +int +write_string (FILE *fp, char *arg) +{ + size_t n = strlen (arg); + return fwrite (arg, n, 1, fp) != 1; +} + +int +write_byte (FILE *fp, char *arg) +{ + int c; + if (strlen (arg) == 3 + && (arg[0] == '\'' || arg[0] == '"')) + c = arg[1]; + else + { + char *p; + unsigned long n = strtoul (arg, &p, 0); + if (*p || n > UCHAR_MAX) + { + errno = EINVAL; + return -1; + } + c = n; + } + return fwrite (&c, 1, 1, fp) != 1; +} + +int +write_short (FILE *fp, char *arg) +{ + uint16_t val; + char *p; + unsigned long n = strtoul (arg, &p, 0); + if (*p || n > UINT16_MAX) + { + errno = EINVAL; + return -1; + } + val = n; + return fwrite (&val, sizeof(val), 1, fp) != 1; +} + +int +write_int (FILE *fp, char *arg) +{ + uint32_t val; + char *p; + unsigned long n = strtoul (arg, &p, 0); + if (*p || n > UINT32_MAX) + { + errno = EINVAL; + return -1; + } + val = n; + return fwrite (&val, sizeof(val), 1, fp) != 1; +} + +static struct dispatch { + char *opt; + int (*act) (FILE *, char *); +} dispatch[] = { + { "-seek", seek_file }, + { "-string", write_string }, + { "-byte", write_byte }, + { "-short", write_short }, + { "-int", write_int }, + { NULL } +}; + +static ACTION +find_action (char const *opt) +{ + struct dispatch *p; + + for (p = dispatch; p->opt; p++) + if (strcmp (p->opt, opt) == 0) + return p->act; + return NULL; +} + +/* + -seek OFF + -string STRING + -byte BYTE + -short SHORT + -int INT + -repeat N + */ +int +main (int argc, char **argv) +{ + char *name; + FILE *fp; + ACTION action; + char **pp; + + assert (argc > 1); + + name = argv[1]; + fp = fopen (name, "w"); + if (!fp) + { + perror (name); + abort (); + } + + pp = argv + 2; + while (*pp) + { + char *opt = *pp++, *arg; + + if (opt[0] != '-') + { + fprintf (stderr, "not an option: %s\n", opt); + abort (); + } + + action = find_action (opt); + if (!action) + { + fprintf (stderr, "unknown action: %s\n", opt); + abort (); + } + + if (!*pp) + { + fprintf (stderr, "argument to %s missing\n", opt); + abort (); + } + arg = *pp++; + if (action (fp, arg)) + { + fprintf (stderr, "%s %s: %s\n", opt, arg, strerror (errno)); + abort (); + } + } + fclose (fp); + return 0; +} diff --git a/mimeview/tests/testsuite.at b/mimeview/tests/testsuite.at new file mode 100644 index 000000000..971b1a211 --- /dev/null +++ b/mimeview/tests/testsuite.at @@ -0,0 +1,200 @@ +# This file is part of GNU Mailutils. -*- Autotest -*- +# Copyright (C) 2017 Free Software Foundation, Inc. +# +# GNU Mailutils is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or (at +# your option) any later version. +# +# GNU Mailutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. + +m4_include([testsuite.inc]) + +dnl ------------------------------------------------------------ +dnl MIMEVIEW_OPTIONS -- default options for mimeview +m4_pushdef([MIMEVIEW_OPTIONS],[--no-site --no-user]) + +m4_pushdef([__prepare_input],[ +m4_if([$1],[],[],[bf $1 $2 +__prepare_input(m4_shift(m4_shift(m4_shift($@))))])]) + +m4_pushdef([prepare_input],[__prepare_input(m4_shift(m4_shift($@)))]) + +m4_pushdef([__select_args],[dnl +m4_if([$2],[],[$1],[dnl +__select_args([$1 $2], m4_shift(m4_shift(m4_shift(m4_shift($@)))))])]) + +m4_pushdef([select_args],[__select_args([],m4_shift(m4_shift($@)))]) + +m4_pushdef([__build_expect],[dnl +m4_if([$2],[],[$1],[__build_expect([dnl +$1[]dnl +$2: $4 +],m4_shift(m4_shift(m4_shift(m4_shift($@)))))])]) + +m4_pushdef([build_expect],[__build_expect([],m4_shift(m4_shift($@)))]) + +# MIMETE |