From a32af27c4c7ef29221d0764a251ff85244c20c64 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Mon, 9 Jul 2018 13:42:25 -0400 Subject: [PATCH] Replace the rest of the uses of __attribute__ that need to be portable (Issue #5349) --- backend/dnssd.c | 40 ++-------- backend/testbackend.c | 2 +- backend/usb-darwin.c | 4 +- berkeley/lpq.c | 2 +- cgi-bin/help-index.c | 6 +- cups/ipp.c | 8 +- cups/testdest.c | 2 +- cups/testsnmp.c | 2 +- cups/versioning.h | 14 ++++ filter/pstops.c | 3 +- scheduler/cups-exec.c | 2 +- scheduler/cupsfilter.c | 2 +- scheduler/ipp.c | 4 +- scheduler/main.c | 2 +- scheduler/testlpd.c | 10 +-- scheduler/testspeed.c | 2 +- scheduler/testsub.c | 2 +- systemv/cupsaddsmb.c | 2 +- systemv/cupsctl.c | 2 +- systemv/cupstestdsc.c | 2 +- systemv/cupstestppd.c | 2 +- systemv/lpoptions.c | 2 +- test/ippfind.c | 40 ++-------- test/ippserver.c | 8 +- test/ipptool.c | 170 ++++++++++++++++++++++++++++++++++++++++- 25 files changed, 221 insertions(+), 114 deletions(-) diff --git a/backend/dnssd.c b/backend/dnssd.c index 7074f4294..fde79ecb9 100644 --- a/backend/dnssd.c +++ b/backend/dnssd.c @@ -82,23 +82,8 @@ static int browsers = 0; /* Number of running browsers */ */ #ifdef HAVE_DNSSD -static void browse_callback(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *serviceName, - const char *regtype, - const char *replyDomain, void *context) - __attribute__((nonnull(1,5,6,7,8))); -static void browse_local_callback(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *serviceName, - const char *regtype, - const char *replyDomain, - void *context) - __attribute__((nonnull(1,5,6,7,8))); +static void browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) _CUPS_NONNULL(1,5,6,7,8); +static void browse_local_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) _CUPS_NONNULL(1,5,6,7,8); #endif /* HAVE_DNSSD */ #ifdef HAVE_AVAHI static void browse_callback(AvahiServiceBrowser *browser, @@ -116,22 +101,10 @@ static void client_callback(AvahiClient *client, #endif /* HAVE_AVAHI */ static int compare_devices(cups_device_t *a, cups_device_t *b); -static void exec_backend(char **argv) __attribute__((noreturn)); -static cups_device_t *get_device(cups_array_t *devices, - const char *serviceName, - const char *regtype, - const char *replyDomain) - __attribute__((nonnull(1,2,3,4))); +static void exec_backend(char **argv) _CUPS_NORETURN; +static cups_device_t *get_device(cups_array_t *devices, const char *serviceName, const char *regtype, const char *replyDomain) _CUPS_NONNULL(1,2,3,4); #ifdef HAVE_DNSSD -static void query_callback(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *fullName, uint16_t rrtype, - uint16_t rrclass, uint16_t rdlen, - const void *rdata, uint32_t ttl, - void *context) - __attribute__((nonnull(1,5,9,11))); +static void query_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullName, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context) _CUPS_NONNULL(1,5,9,11); #elif defined(HAVE_AVAHI) static int poll_callback(struct pollfd *pollfds, unsigned int num_pollfds, int timeout, @@ -147,8 +120,7 @@ static void query_callback(AvahiRecordBrowser *browser, void *context); #endif /* HAVE_DNSSD */ static void sigterm_handler(int sig); -static void unquote(char *dst, const char *src, size_t dstsize) - __attribute__((nonnull(1,2))); +static void unquote(char *dst, const char *src, size_t dstsize) _CUPS_NONNULL(1,2); /* diff --git a/backend/testbackend.c b/backend/testbackend.c index b8dbe3bd1..6dbd0abee 100644 --- a/backend/testbackend.c +++ b/backend/testbackend.c @@ -33,7 +33,7 @@ static int job_canceled = 0; */ static void sigterm_handler(int sig); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; static void walk_cb(const char *oid, const char *data, int datalen, void *context); diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index 4f31d031a..4a85b4766 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -290,10 +290,10 @@ static void status_timer_cb(CFRunLoopTimerRef timer, void *info); #if defined(__i386__) || defined(__x86_64__) static pid_t child_pid; /* Child PID */ -static void run_legacy_backend(int argc, char *argv[], int fd) __attribute__((noreturn)); /* Starts child backend process running as a ppc executable */ +static void run_legacy_backend(int argc, char *argv[], int fd) _CUPS_NORETURN; /* Starts child backend process running as a ppc executable */ #endif /* __i386__ || __x86_64__ */ static void sigterm_handler(int sig); /* SIGTERM handler */ -static void sigquit_handler(int sig, siginfo_t *si, void *unused) __attribute__((noreturn)); +static void sigquit_handler(int sig, siginfo_t *si, void *unused) _CUPS_NORETURN; #ifdef PARSE_PS_ERRORS static const char *next_line (const char *buffer); diff --git a/berkeley/lpq.c b/berkeley/lpq.c index eec41dbb6..47220f5d7 100644 --- a/berkeley/lpq.c +++ b/berkeley/lpq.c @@ -22,7 +22,7 @@ static http_t *connect_server(const char *, http_t *); static int show_jobs(const char *, http_t *, const char *, const char *, const int, const int); static void show_printer(const char *, http_t *, const char *); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; /* diff --git a/cgi-bin/help-index.c b/cgi-bin/help-index.c index 8e00f0467..5f76d7aa5 100644 --- a/cgi-bin/help-index.c +++ b/cgi-bin/help-index.c @@ -134,11 +134,7 @@ static int help_load_file(help_index_t *hi, const char *filename, const char *relative, time_t mtime); -static help_node_t *help_new_node(const char *filename, const char *anchor, - const char *section, const char *text, - time_t mtime, off_t offset, - size_t length) - __attribute__((nonnull(1,3,4))); +static help_node_t *help_new_node(const char *filename, const char *anchor, const char *section, const char *text, time_t mtime, off_t offset, size_t length) _CUPS_NONNULL(1,3,4); static int help_sort_by_name(help_node_t *p1, help_node_t *p2); static int help_sort_by_score(help_node_t *p1, help_node_t *p2); static int help_sort_words(help_word_t *w1, help_word_t *w2); diff --git a/cups/ipp.c b/cups/ipp.c index 325de02b9..904380c6d 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -28,12 +28,8 @@ static ipp_attribute_t *ipp_add_attr(ipp_t *ipp, const char *name, int num_values); static void ipp_free_values(ipp_attribute_t *attr, int element, int count); -static char *ipp_get_code(const char *locale, char *buffer, - size_t bufsize) - __attribute__((nonnull(1,2))); -static char *ipp_lang_code(const char *locale, char *buffer, - size_t bufsize) - __attribute__((nonnull(1,2))); +static char *ipp_get_code(const char *locale, char *buffer, size_t bufsize) _CUPS_NONNULL(1,2); +static char *ipp_lang_code(const char *locale, char *buffer, size_t bufsize) _CUPS_NONNULL(1,2); static size_t ipp_length(ipp_t *ipp, int collection); static ssize_t ipp_read_http(http_t *http, ipp_uchar_t *buffer, size_t length); diff --git a/cups/testdest.c b/cups/testdest.c index 7381ba34e..a65e09960 100644 --- a/cups/testdest.c +++ b/cups/testdest.c @@ -26,7 +26,7 @@ static void show_conflicts(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, static void show_default(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option); static void show_media(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, unsigned flags, const char *name); static void show_supported(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value); -static void usage(const char *arg) __attribute__((noreturn)); +static void usage(const char *arg) _CUPS_NORETURN; /* diff --git a/cups/testsnmp.c b/cups/testsnmp.c index 7a493e1f0..8071847a7 100644 --- a/cups/testsnmp.c +++ b/cups/testsnmp.c @@ -21,7 +21,7 @@ static void print_packet(cups_snmp_t *packet, void *data); static int show_oid(int fd, const char *community, http_addr_t *addr, const char *s, int walk); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; /* diff --git a/cups/versioning.h b/cups/versioning.h index 12328d688..19cd186a6 100644 --- a/cups/versioning.h +++ b/cups/versioning.h @@ -25,6 +25,7 @@ * - _CUPS_INTERNAL_MSG("msg"): Function is * - _CUPS_NONNULL((arg list)): Specifies the comma-separated argument indices * are assumed non-NULL. Indices start at 1. + * - _CUPS_NORETURN: Specifies the function does not return. * - _CUPS_PRIVATE: Specifies the function is private to CUPS. * - _CUPS_PUBLIC: Specifies the function is public API. */ @@ -41,6 +42,7 @@ # ifdef __has_extension /* Clang */ # define _CUPS_HAS_DEPRECATED # define _CUPS_HAS_FORMAT +# define _CUPS_HAS_NORETURN # define _CUPS_HAS_VISIBILITY # if __has_extension(attribute_deprecated_with_message) # define _CUPS_HAS_DEPRECATED_WITH_MESSAGE @@ -52,6 +54,7 @@ # if __GNUC__ >= 3 /* GCC 3.0 or higher */ # define _CUPS_HAS_DEPRECATED # define _CUPS_HAS_FORMAT +# define _CUPS_HAS_NORETURN # define _CUPS_HAS_VISIBILITY # endif /* __GNUC__ >= 3 */ # if __GNUC__ >= 5 /* GCC 5.x */ @@ -231,4 +234,15 @@ # endif /* _CUPS_HAS_FORMAT */ +/* + * Define _CUPS_NORETURN macro for functions that don't return. + */ + +# ifdef _CUPS_HAS_NORETURN +# define _CUPS_NORETURN __attribute__ ((noreturn)) +# else +# define _CUPS_NORETURN +# endif /* _CUPS_HAS_NORETURN */ + + #endif /* !_CUPS_VERSIONING_H_ */ diff --git a/filter/pstops.c b/filter/pstops.c index 906a6e78c..d251abb0e 100644 --- a/filter/pstops.c +++ b/filter/pstops.c @@ -157,8 +157,7 @@ static ssize_t copy_trailer(cups_file_t *fp, pstops_doc_t *doc, ssize_t linelen, size_t linesize); static void do_prolog(pstops_doc_t *doc, ppd_file_t *ppd); static void do_setup(pstops_doc_t *doc, ppd_file_t *ppd); -static void doc_printf(pstops_doc_t *doc, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); +static void doc_printf(pstops_doc_t *doc, const char *format, ...) _CUPS_FORMAT(2, 3); static void doc_puts(pstops_doc_t *doc, const char *s); static void doc_write(pstops_doc_t *doc, const char *s, size_t len); static void end_nup(pstops_doc_t *doc, int number); diff --git a/scheduler/cups-exec.c b/scheduler/cups-exec.c index abda0d597..674de0a3a 100644 --- a/scheduler/cups-exec.c +++ b/scheduler/cups-exec.c @@ -33,7 +33,7 @@ * Local functions... */ -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; /* diff --git a/scheduler/cupsfilter.c b/scheduler/cupsfilter.c index 811d3fc13..fa914d215 100644 --- a/scheduler/cupsfilter.c +++ b/scheduler/cupsfilter.c @@ -78,7 +78,7 @@ static int open_pipe(int *fds); static int read_cups_files_conf(const char *filename); static void set_string(char **s, const char *val); static void sighandler(int sig); -static void usage(const char *opt) __attribute__((noreturn)); +static void usage(const char *opt) _CUPS_NORETURN; /* diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 89058d285..979b31a8b 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -115,9 +115,7 @@ static void save_auth_info(cupsd_client_t *con, cupsd_job_t *job, static void send_document(cupsd_client_t *con, ipp_attribute_t *uri); static void send_http_error(cupsd_client_t *con, http_status_t status, cupsd_printer_t *printer); -static void send_ipp_status(cupsd_client_t *con, ipp_status_t status, - const char *message, ...) - __attribute__((__format__(__printf__, 3, 4))); +static void send_ipp_status(cupsd_client_t *con, ipp_status_t status, const char *message, ...) _CUPS_FORMAT(3, 4); static void set_default(cupsd_client_t *con, ipp_attribute_t *uri); static void set_job_attrs(cupsd_client_t *con, ipp_attribute_t *uri); static void set_printer_attrs(cupsd_client_t *con, ipp_attribute_t *uri); diff --git a/scheduler/main.c b/scheduler/main.c index d022aa204..a992b540d 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -66,7 +66,7 @@ static void sigterm_handler(int sig); static long select_timeout(int fds); static void service_checkin(void); static void service_checkout(int shutdown); -static void usage(int status) __attribute__((noreturn)); +static void usage(int status) _CUPS_NORETURN; /* diff --git a/scheduler/testlpd.c b/scheduler/testlpd.c index 58447a0a3..d974c5269 100644 --- a/scheduler/testlpd.c +++ b/scheduler/testlpd.c @@ -25,12 +25,12 @@ */ static int do_command(int outfd, int infd, const char *command); -static int print_job(int outfd, int infd, char *dest, char **args) __attribute__((nonnull(4))); +static int print_job(int outfd, int infd, char *dest, char **args) _CUPS_NONNULL(4); static int print_waiting(int outfd, int infd, char *dest); -static int remove_job(int outfd, int infd, char *dest, char **args) __attribute__((nonnull(4))); -static int status_long(int outfd, int infd, char *dest, char **args) __attribute__((nonnull(4))); -static int status_short(int outfd, int infd, char *dest, char **args) __attribute__((nonnull(4))); -static void usage(void) __attribute__((noreturn)); +static int remove_job(int outfd, int infd, char *dest, char **args) _CUPS_NONNULL(4); +static int status_long(int outfd, int infd, char *dest, char **args) _CUPS_NONNULL(4); +static int status_short(int outfd, int infd, char *dest, char **args) _CUPS_NONNULL(4); +static void usage(void) _CUPS_NORETURN; /* diff --git a/scheduler/testspeed.c b/scheduler/testspeed.c index 0aa36e9d9..7cd875c97 100644 --- a/scheduler/testspeed.c +++ b/scheduler/testspeed.c @@ -27,7 +27,7 @@ static int do_test(const char *server, int port, http_encryption_t encryption, int requests, const char *opstring, int verbose); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; /* diff --git a/scheduler/testsub.c b/scheduler/testsub.c index 08f0f7465..19d9dffce 100644 --- a/scheduler/testsub.c +++ b/scheduler/testsub.c @@ -31,7 +31,7 @@ static int terminate = 0; static void print_attributes(ipp_t *ipp, int indent); static void sigterm_handler(int sig); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; /* diff --git a/systemv/cupsaddsmb.c b/systemv/cupsaddsmb.c index b995c0386..d1f9ac287 100644 --- a/systemv/cupsaddsmb.c +++ b/systemv/cupsaddsmb.c @@ -33,7 +33,7 @@ const char *SAMBAUser, */ int export_dest(http_t *http, const char *dest); -void usage(void) __attribute__((noreturn)); +void usage(void) _CUPS_NORETURN; /* diff --git a/systemv/cupsctl.c b/systemv/cupsctl.c index eedd01344..053029b23 100644 --- a/systemv/cupsctl.c +++ b/systemv/cupsctl.c @@ -19,7 +19,7 @@ * Local functions... */ -static void usage(const char *opt) __attribute__((noreturn)); +static void usage(const char *opt) _CUPS_NORETURN; /* diff --git a/systemv/cupstestdsc.c b/systemv/cupstestdsc.c index be332a411..085037511 100644 --- a/systemv/cupstestdsc.c +++ b/systemv/cupstestdsc.c @@ -21,7 +21,7 @@ */ static int check_file(const char *filename); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; /* diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c index 75c303281..1880a2dfa 100644 --- a/systemv/cupstestppd.c +++ b/systemv/cupstestppd.c @@ -101,7 +101,7 @@ static int check_translations(ppd_file_t *ppd, int errors, int verbose, int warn); static void show_conflicts(ppd_file_t *ppd, const char *prefix); static int test_raster(ppd_file_t *ppd, int verbose); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; static int valid_path(const char *keyword, const char *path, int errors, int verbose, int warn); static int valid_utf8(const char *s); diff --git a/systemv/lpoptions.c b/systemv/lpoptions.c index ca148cd63..f80319a19 100644 --- a/systemv/lpoptions.c +++ b/systemv/lpoptions.c @@ -21,7 +21,7 @@ static void list_group(ppd_file_t *ppd, ppd_group_t *group); static void list_options(cups_dest_t *dest); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; /* diff --git a/test/ippfind.c b/test/ippfind.c index 79c0a0655..2993ea7f8 100644 --- a/test/ippfind.c +++ b/test/ippfind.c @@ -144,23 +144,8 @@ static int ipp_version = 20; /* IPP version for LIST */ */ #ifdef HAVE_DNSSD -static void DNSSD_API browse_callback(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *serviceName, - const char *regtype, - const char *replyDomain, void *context) - __attribute__((nonnull(1,5,6,7,8))); -static void DNSSD_API browse_local_callback(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *serviceName, - const char *regtype, - const char *replyDomain, - void *context) - __attribute__((nonnull(1,5,6,7,8))); +static void DNSSD_API browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) _CUPS_NONNULL(1,5,6,7,8); +static void DNSSD_API browse_local_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) _CUPS_NONNULL(1,5,6,7,8); #elif defined(HAVE_AVAHI) static void browse_callback(AvahiServiceBrowser *browser, AvahiIfIndex interface, @@ -182,27 +167,14 @@ static int eval_expr(ippfind_srv_t *service, ippfind_expr_t *expressions); static int exec_program(ippfind_srv_t *service, int num_args, char **args); -static ippfind_srv_t *get_service(cups_array_t *services, - const char *serviceName, - const char *regtype, - const char *replyDomain) - __attribute__((nonnull(1,2,3,4))); +static ippfind_srv_t *get_service(cups_array_t *services, const char *serviceName, const char *regtype, const char *replyDomain) _CUPS_NONNULL(1,2,3,4); static double get_time(void); static int list_service(ippfind_srv_t *service); static ippfind_expr_t *new_expr(ippfind_op_t op, int invert, const char *value, const char *regex, char **args); #ifdef HAVE_DNSSD -static void DNSSD_API resolve_callback(DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *fullName, - const char *hostTarget, uint16_t port, - uint16_t txtLen, - const unsigned char *txtRecord, - void *context) - __attribute__((nonnull(1,5,6,9, 10))); +static void DNSSD_API resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullName, const char *hostTarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) _CUPS_NONNULL(1,5,6,9, 10); #elif defined(HAVE_AVAHI) static int poll_callback(struct pollfd *pollfds, unsigned int num_pollfds, int timeout, @@ -222,8 +194,8 @@ static void resolve_callback(AvahiServiceResolver *res, void *context); #endif /* HAVE_DNSSD */ static void set_service_uri(ippfind_srv_t *service); -static void show_usage(void) __attribute__((noreturn)); -static void show_version(void) __attribute__((noreturn)); +static void show_usage(void) _CUPS_NORETURN; +static void show_version(void) _CUPS_NORETURN; /* diff --git a/test/ippserver.c b/test/ippserver.c index e2bdbb2c0..8769094e8 100644 --- a/test/ippserver.c +++ b/test/ippserver.c @@ -405,8 +405,7 @@ static void html_escape(_ipp_client_t *client, const char *s, static void html_footer(_ipp_client_t *client); static void html_header(_ipp_client_t *client, const char *title); static void html_printf(_ipp_client_t *client, const char *format, - ...) __attribute__((__format__(__printf__, - 2, 3))); + ...) _CUPS_FORMAT(2, 3); static void ipp_cancel_job(_ipp_client_t *client); static void ipp_close_job(_ipp_client_t *client); static void ipp_create_job(_ipp_client_t *client); @@ -432,13 +431,12 @@ static int respond_http(_ipp_client_t *client, http_status_t code, const char *content_coding, const char *type, size_t length); static void respond_ipp(_ipp_client_t *client, ipp_status_t status, - const char *message, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); + const char *message, ...) _CUPS_FORMAT(3, 4); static void respond_unsupported(_ipp_client_t *client, ipp_attribute_t *attr); static void run_printer(_ipp_printer_t *printer); static char *time_string(time_t tv, char *buffer, size_t bufsize); -static void usage(int status) __attribute__((noreturn)); +static void usage(int status) _CUPS_NORETURN; static int valid_doc_attributes(_ipp_client_t *client); static int valid_job_attributes(_ipp_client_t *client); diff --git a/test/ipptool.c b/test/ipptool.c index 697ea8a96..39ccb286b 100644 --- a/test/ipptool.c +++ b/test/ipptool.c @@ -165,8 +165,9 @@ static int Cancel = 0; /* Cancel test? */ * Local functions... */ -static void add_stringf(cups_array_t *a, const char *s, ...) __attribute__ ((__format__ (__printf__, 2, 3))); +static void add_stringf(cups_array_t *a, const char *s, ...) _CUPS_FORMAT(2, 3); static int compare_uris(const char *a, const char *b); +static void copy_hex_string(char *buffer, unsigned char *data, int datalen, size_t bufsize); static int do_test(_ipp_file_t *f, _ipp_vars_t *vars, _cups_testdata_t *data); static int do_tests(const char *testfile, _ipp_vars_t *vars, _cups_testdata_t *data); static int error_cb(_ipp_file_t *f, _cups_testdata_t *data, const char *error); @@ -178,7 +179,7 @@ static char *iso_date(const ipp_uchar_t *date); static void pause_message(const char *message); static void print_attr(cups_file_t *outfile, int output, ipp_attribute_t *attr, ipp_tag_t *group); static void print_csv(_cups_testdata_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths); -static void print_fatal_error(_cups_testdata_t *data, const char *s, ...) __attribute__ ((__format__ (__printf__, 2, 3))); +static void print_fatal_error(_cups_testdata_t *data, const char *s, ...) _CUPS_FORMAT(2, 3); static void print_ippserver_attr(_cups_testdata_t *data, ipp_attribute_t *attr, int indent); static void print_ippserver_string(_cups_testdata_t *data, const char *s, size_t len); static void print_line(_cups_testdata_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths); @@ -190,7 +191,7 @@ static void sigterm_handler(int sig); #endif /* WIN32 */ static int timeout_cb(http_t *http, void *user_data); static int token_cb(_ipp_file_t *f, _ipp_vars_t *vars, _cups_testdata_t *data, const char *token); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; static const char *with_flags_string(int flags); static int with_value(_cups_testdata_t *data, cups_array_t *errors, char *value, int flags, ipp_attribute_t *attr, char *matchbuf, size_t matchlen); static int with_value_from(cups_array_t *errors, ipp_attribute_t *fromattr, ipp_attribute_t *attr, char *matchbuf, size_t matchlen); @@ -816,6 +817,69 @@ compare_uris(const char *a, /* I - First URI */ } +/* + * 'copy_hex_string()' - Copy an octetString to a C string and encode as hex if + * needed. + */ + +static void +copy_hex_string(char *buffer, /* I - String buffer */ + unsigned char *data, /* I - octetString data */ + int datalen, /* I - octetString length */ + size_t bufsize) /* I - Size of string buffer */ +{ + char *bufptr, /* Pointer into string buffer */ + *bufend = buffer + bufsize - 2; + /* End of string buffer */ + unsigned char *dataptr, /* Pointer into octetString data */ + *dataend = data + datalen; + /* End of octetString data */ + static const char *hexdigits = "0123456789ABCDEF"; + /* Hex digits */ + + + /* + * First see if there are any non-ASCII bytes in the octetString... + */ + + for (dataptr = data; dataptr < dataend; dataptr ++) + if (*dataptr < 0x20 || *dataptr >= 0x7f) + break; + + if (*dataptr) + { + /* + * Yes, encode as hex... + */ + + *buffer = '<'; + + for (bufptr = buffer + 1, dataptr = data; bufptr < bufend && dataptr < dataend; dataptr ++) + { + *bufptr++ = hexdigits[*dataptr >> 4]; + *bufptr++ = hexdigits[*dataptr & 15]; + } + + if (bufptr < bufend) + *bufptr++ = '>'; + + *bufptr = '\0'; + } + else + { + /* + * No, copy as a string... + */ + + if ((size_t)datalen > bufsize) + datalen = (int)bufsize - 1; + + memcpy(buffer, data, datalen); + buffer[datalen] = '\0'; + } +} + + /* * 'do_test()' - Do a single test from the test file. */ @@ -1351,7 +1415,12 @@ do_test(_ipp_file_t *f, /* I - IPP data file */ _ippVarsGet(vars, expect->if_not_defined)) continue; - found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO); + if ((found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO)) != NULL && expect->in_group && expect->in_group != ippGetGroupTag(found)) + { + while ((found = ippFindNextAttribute(response, expect->name, IPP_TAG_ZERO)) != NULL) + if (expect->in_group == ippGetGroupTag(found)) + break; + } do { @@ -4701,6 +4770,99 @@ with_value(_cups_testdata_t *data, /* I - Test data */ } break; + case IPP_TAG_STRING : + { + unsigned char withdata[1023], /* WITH-VALUE data */ + *adata; /* Pointer to octetString data */ + int withlen, /* Length of WITH-VALUE data */ + adatalen; /* Length of octetString */ + + if (*value == '<') + { + /* + * Grab hex-encoded value... + */ + + if ((withlen = (int)strlen(value)) & 1 || withlen > (2 * (sizeof(withdata) + 1))) + { + print_fatal_error(data, "Bad WITH-VALUE hex value."); + return (0); + } + + withlen = withlen / 2 - 1; + + for (valptr = value + 1, adata = withdata; *valptr; valptr += 2) + { + int ch; /* Current character/byte */ + + if (isdigit(valptr[0])) + ch = (valptr[0] - '0') << 4; + else if (isalpha(valptr[0])) + ch = (tolower(valptr[0]) - 'a' + 10) << 4; + else + break; + + if (isdigit(valptr[1])) + ch |= valptr[1] - '0'; + else if (isalpha(valptr[1])) + ch |= tolower(valptr[1]) - 'a' + 10; + else + break; + + *adata++ = (unsigned char)ch; + } + + if (*valptr) + { + print_fatal_error(data, "Bad WITH-VALUE hex value."); + return (0); + } + } + else + { + /* + * Copy literal string value... + */ + + withlen = (int)strlen(value); + + memcpy(withdata, value, withlen); + } + + for (i = 0; i < count; i ++) + { + adata = ippGetOctetString(attr, i, &adatalen); + + if (withlen == adatalen && !memcmp(withdata, adata, (size_t)withlen)) + { + if (!matchbuf[0]) + copy_hex_string(matchbuf, adata, adatalen, matchlen); + + if (!(flags & _CUPS_WITH_ALL)) + { + match = 1; + break; + } + } + else if (flags & _CUPS_WITH_ALL) + { + match = 0; + break; + } + } + + if (!match && errors) + { + for (i = 0; i < count; i ++) + { + adata = ippGetOctetString(attr, i, &adatalen); + copy_hex_string(temp, adata, adatalen, sizeof(temp)); + add_stringf(data->errors, "GOT: %s=\"%s\"", name, temp); + } + } + } + break; + default : break; } -- 2.39.5