core: enable compiler warngings for report_error and report_info

printf() is a horrible interface as it does no type checking.
Let's at least use the compiler to check format strings and
arguments. This obviously doesn't work for translated strings
and using report_error on translated strings is dubious. But OK.

Had to convert a number of report_error() calls to supress
warnings.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-03-12 09:17:50 +01:00 committed by Dirk Hohndel
parent fcf0bda042
commit bfbf4934dd
13 changed files with 39 additions and 33 deletions

View file

@ -97,7 +97,7 @@ void CloudStorageAuthenticate::uploadFinished()
} else if (cloudAuthReply == QLatin1String("[VERIFY]") || } else if (cloudAuthReply == QLatin1String("[VERIFY]") ||
cloudAuthReply == QLatin1String("Invalid PIN")) { cloudAuthReply == QLatin1String("Invalid PIN")) {
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NEED_TO_VERIFY); qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NEED_TO_VERIFY);
report_error(qPrintable(tr("Cloud account verification required, enter PIN in preferences"))); report_error("%s", qPrintable(tr("Cloud account verification required, enter PIN in preferences")));
} else if (cloudAuthReply == QLatin1String("[PASSWDCHANGED]")) { } else if (cloudAuthReply == QLatin1String("[PASSWDCHANGED]")) {
qPrefCloudStorage::set_cloud_storage_password(cloudNewPassword); qPrefCloudStorage::set_cloud_storage_password(cloudNewPassword);
cloudNewPassword.clear(); cloudNewPassword.clear();

View file

@ -594,7 +594,7 @@ QString ConfigureDiveComputer::dc_open(device_data_t *data)
rc = divecomputer_device_open(data); rc = divecomputer_device_open(data);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
report_error(errmsg(rc)); report_error("%s", errmsg(rc));
} else { } else {
rc = dc_device_open(&data->device, data->context, data->descriptor, data->iostream); rc = dc_device_open(&data->device, data->context, data->descriptor, data->iostream);
} }

View file

@ -688,7 +688,7 @@ int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log)
// Verify fileheader, get number of dives in datatrak divelog, zero on error // Verify fileheader, get number of dives in datatrak divelog, zero on error
numdives = read_file_header((unsigned char *)mem.data()); numdives = read_file_header((unsigned char *)mem.data());
if (!numdives) { if (!numdives) {
report_error(translate("gettextFromC", "[Error] File is not a DataTrak file. Aborted")); report_error("%s", translate("gettextFromC", "[Error] File is not a DataTrak file. Aborted"));
goto bail; goto bail;
} }
// Verify WLog .add file, Beginning sequence and Nº dives // Verify WLog .add file, Beginning sequence and Nº dives
@ -711,7 +711,7 @@ int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log)
if (!wl_mem.empty()) if (!wl_mem.empty())
wlog_compl_parser(wl_mem, ptdive, i); wlog_compl_parser(wl_mem, ptdive, i);
if (runner == NULL) { if (runner == NULL) {
report_error(translate("gettextFromC", "Error: no dive")); report_error("%s", translate("gettextFromC", "Error: no dive"));
free(ptdive); free(ptdive);
rc = 1; rc = 1;
goto out; goto out;

View file

@ -149,7 +149,7 @@ void exportHtmlInitLogic(const QString &filename, struct htmlExportSetting &hes)
QString searchPath = getSubsurfaceDataPath("theme"); QString searchPath = getSubsurfaceDataPath("theme");
if (searchPath.isEmpty()) { if (searchPath.isEmpty()) {
report_error(qPrintable(gettextFromC::tr("Cannot find a folder called 'theme' in the standard locations"))); report_error("%s", qPrintable(gettextFromC::tr("Cannot find a folder called 'theme' in the standard locations")));
return; return;
} }

View file

@ -8,9 +8,15 @@
extern "C" { extern "C" {
#endif #endif
#ifdef __GNUC__
#define __printf(x, y) __attribute__((__format__(__printf__, x, y)))
#else
#define __printf(x, y)
#endif
extern int verbose; extern int verbose;
extern int report_error(const char *fmt, ...); extern int __printf(1, 2) report_error(const char *fmt, ...);
extern void report_info(const char *fmt, ...); extern void __printf(1, 2) report_info(const char *fmt, ...);
extern void set_error_cb(void(*cb)(char *)); // Callback takes ownership of passed string extern void set_error_cb(void(*cb)(char *)); // Callback takes ownership of passed string
#define SSRF_INFO(fmt, ...) report_info(fmt, ##__VA_ARGS__) #define SSRF_INFO(fmt, ...) report_info(fmt, ##__VA_ARGS__)

View file

@ -191,7 +191,7 @@ static int reset_to_remote(struct git_info *info, git_reference *local, const gi
if (git_reference_set_target(&out, local, new_id, "Update to remote")) { if (git_reference_set_target(&out, local, new_id, "Update to remote")) {
SSRF_INFO("git storage: could not update local cache to newer remote data"); SSRF_INFO("git storage: could not update local cache to newer remote data");
return report_error(translate("gettextFromC", "Could not update local cache to newer remote data")); return report_error("%s", translate("gettextFromC", "Could not update local cache to newer remote data"));
} }
git_reference_free(out); git_reference_free(out);
@ -205,7 +205,7 @@ static int reset_to_remote(struct git_info *info, git_reference *local, const gi
if (git_object_lookup(&target, info->repo, new_id, GIT_OBJ_COMMIT)) { if (git_object_lookup(&target, info->repo, new_id, GIT_OBJ_COMMIT)) {
SSRF_INFO("git storage: could not look up remote commit"); SSRF_INFO("git storage: could not look up remote commit");
if (info->is_subsurface_cloud) if (info->is_subsurface_cloud)
return report_error(translate("gettextFromC", "Subsurface cloud storage corrupted")); return report_error("%s", translate("gettextFromC", "Subsurface cloud storage corrupted"));
else else
return report_error("Could not look up remote commit"); return report_error("Could not look up remote commit");
} }
@ -213,7 +213,7 @@ static int reset_to_remote(struct git_info *info, git_reference *local, const gi
if (git_reset(info->repo, target, GIT_RESET_HARD, &opts)) { if (git_reset(info->repo, target, GIT_RESET_HARD, &opts)) {
SSRF_INFO("git storage: local head checkout failed after update"); SSRF_INFO("git storage: local head checkout failed after update");
if (info->is_subsurface_cloud) if (info->is_subsurface_cloud)
return report_error(translate("gettextFromC", "Could not update local cache to newer remote data")); return report_error("%s", translate("gettextFromC", "Could not update local cache to newer remote data"));
else else
return report_error("Local head checkout failed after update"); return report_error("Local head checkout failed after update");
} }
@ -331,7 +331,7 @@ static int update_remote(struct git_info *info, git_remote *origin, git_referenc
const char *msg = giterr_last()->message; const char *msg = giterr_last()->message;
SSRF_INFO("git storage: unable to update remote with current local cache state, error: %s", msg); SSRF_INFO("git storage: unable to update remote with current local cache state, error: %s", msg);
if (info->is_subsurface_cloud) if (info->is_subsurface_cloud)
return report_error(translate("gettextFromC", "Could not update Subsurface cloud storage, try again later")); return report_error("%s", translate("gettextFromC", "Could not update Subsurface cloud storage, try again later"));
else else
return report_error("Unable to update remote with current local cache state (%s)", msg); return report_error("Unable to update remote with current local cache state (%s)", msg);
} }
@ -417,7 +417,7 @@ static int try_to_git_merge(struct git_info *info, git_reference **local_p, git_
} }
git_index_conflict_cleanup(merged_index); git_index_conflict_cleanup(merged_index);
git_index_conflict_iterator_free(iter); git_index_conflict_iterator_free(iter);
report_error(translate("gettextFromC", "Remote storage and local data diverged. Cannot combine local and remote changes")); report_error("%s", translate("gettextFromC", "Remote storage and local data diverged. Cannot combine local and remote changes"));
} }
{ {
git_oid merge_oid, commit_oid; git_oid merge_oid, commit_oid;
@ -455,7 +455,7 @@ static int try_to_git_merge(struct git_info *info, git_reference **local_p, git_
} }
diverged_error: diverged_error:
return report_error(translate("gettextFromC", "Remote storage and local data diverged")); return report_error("%s", translate("gettextFromC", "Remote storage and local data diverged"));
write_error: write_error:
free_buffer(&msg); free_buffer(&msg);
@ -469,7 +469,7 @@ static int cleanup_local_cache(struct git_info *info)
{ {
char *backup_path = move_local_cache(info); char *backup_path = move_local_cache(info);
SSRF_INFO("git storage: problems with local cache, moved to %s", backup_path); SSRF_INFO("git storage: problems with local cache, moved to %s", backup_path);
report_error(translate("gettextFromC", "Problems with local cache of Subsurface cloud data")); report_error("%s", translate("gettextFromC", "Problems with local cache of Subsurface cloud data"));
report_error(translate("gettextFromC", "Moved cache data to %s. Please try the operation again."), backup_path); report_error(translate("gettextFromC", "Moved cache data to %s. Please try the operation again."), backup_path);
free(backup_path); free(backup_path);
return -1; return -1;
@ -884,7 +884,7 @@ static bool create_local_repo(struct git_info *info)
error = 0; error = 0;
#if !defined(DEBUG) && !defined(SUBSURFACE_MOBILE) #if !defined(DEBUG) && !defined(SUBSURFACE_MOBILE)
} else if (info->is_subsurface_cloud) { } else if (info->is_subsurface_cloud) {
report_error(translate("gettextFromC", "Error connecting to Subsurface cloud storage")); report_error("%s", translate("gettextFromC", "Error connecting to Subsurface cloud storage"));
#endif #endif
} else { } else {
report_error(translate("gettextFromC", "git clone of %s failed (%s)"), info->url, msg); report_error(translate("gettextFromC", "git clone of %s failed (%s)"), info->url, msg);

View file

@ -1500,7 +1500,7 @@ const char *do_libdivecomputer_import(device_data_t *data)
rc = divecomputer_device_open(data); rc = divecomputer_device_open(data);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
report_error(errmsg(rc)); report_error("%s", errmsg(rc));
} else { } else {
dev_info(data, "Connecting ..."); dev_info(data, "Connecting ...");
rc = dc_device_open(&data->device, data->context, data->descriptor, data->iostream); rc = dc_device_open(&data->device, data->context, data->descriptor, data->iostream);

View file

@ -73,7 +73,7 @@ bool uploadDiveLogsDE::prepareDives(const QString &tempfile, bool selected)
xslt = get_stylesheet("divelogs-export.xslt"); xslt = get_stylesheet("divelogs-export.xslt");
if (!xslt) { if (!xslt) {
qDebug() << errPrefix << "missing stylesheet"; qDebug() << errPrefix << "missing stylesheet";
report_error(tr("Stylesheet to export to divelogs.de is not found").toUtf8()); report_error("%s", qPrintable(tr("Stylesheet to export to divelogs.de is not found")));
return false; return false;
} }
@ -83,7 +83,7 @@ bool uploadDiveLogsDE::prepareDives(const QString &tempfile, bool selected)
if (!zip) { if (!zip) {
char buffer[1024]; char buffer[1024];
zip_error_to_str(buffer, sizeof buffer, error_code, errno); zip_error_to_str(buffer, sizeof buffer, error_code, errno);
report_error(tr("Failed to create zip file for upload: %s").toUtf8(), buffer); report_error(qPrintable(tr("Failed to create zip file for upload: %s")), buffer);
return false; return false;
} }
@ -144,7 +144,7 @@ bool uploadDiveLogsDE::prepareDives(const QString &tempfile, bool selected)
xmlDoc *doc = xmlReadMemory(mb.buffer, mb.len, "divelog", NULL, XML_PARSE_HUGE | XML_PARSE_RECOVER); xmlDoc *doc = xmlReadMemory(mb.buffer, mb.len, "divelog", NULL, XML_PARSE_HUGE | XML_PARSE_RECOVER);
if (!doc) { if (!doc) {
qWarning() << errPrefix << "could not parse back into memory the XML file we've just created!"; qWarning() << errPrefix << "could not parse back into memory the XML file we've just created!";
report_error(tr("internal error").toUtf8()); report_error("%s", qPrintable(tr("internal error")));
zip_close(zip); zip_close(zip);
QFile::remove(tempfile); QFile::remove(tempfile);
xsltFreeStylesheet(xslt); xsltFreeStylesheet(xslt);
@ -157,7 +157,7 @@ bool uploadDiveLogsDE::prepareDives(const QString &tempfile, bool selected)
free_xml_params(params); free_xml_params(params);
if (!transformed) { if (!transformed) {
qWarning() << errPrefix << "XSLT transform failed for dive: " << i; qWarning() << errPrefix << "XSLT transform failed for dive: " << i;
report_error(tr("Conversion of dive %1 to divelogs.de format failed").arg(i).toUtf8()); report_error("%s", qPrintable(tr("Conversion of dive %1 to divelogs.de format failed").arg(i)));
continue; continue;
} }
xmlDocDumpMemory(transformed, (xmlChar **)&membuf, &streamsize); xmlDocDumpMemory(transformed, (xmlChar **)&membuf, &streamsize);
@ -310,7 +310,7 @@ void uploadDiveLogsDE::uploadFinishedSlot()
if (parsed) { if (parsed) {
if (strstr(resp, "<Login>succeeded</Login>")) { if (strstr(resp, "<Login>succeeded</Login>")) {
if (strstr(resp, "<FileCopy>failed</FileCopy>")) { if (strstr(resp, "<FileCopy>failed</FileCopy>")) {
report_error(tr("Upload failed").toUtf8()); report_error("%s", qPrintable(tr("Upload failed")));
return; return;
} }
timeout.stop(); timeout.stop();
@ -320,13 +320,13 @@ void uploadDiveLogsDE::uploadFinishedSlot()
} }
timeout.stop(); timeout.stop();
err = tr("Login failed"); err = tr("Login failed");
report_error(err.toUtf8()); report_error("%s", qPrintable(err));
emit uploadFinish(false, err); emit uploadFinish(false, err);
return; return;
} }
timeout.stop(); timeout.stop();
err = tr("Cannot parse response"); err = tr("Cannot parse response");
report_error(tr("Cannot parse response").toUtf8()); report_error("%s", qPrintable(tr("Cannot parse response")));
emit uploadFinish(false, err); emit uploadFinish(false, err);
} }
} }
@ -341,7 +341,7 @@ void uploadDiveLogsDE::uploadTimeoutSlot()
} }
cleanupTempFile(); cleanupTempFile();
QString err(tr("divelogs.de not responding")); QString err(tr("divelogs.de not responding"));
report_error(err.toUtf8()); report_error("%s", qPrintable(err));
emit uploadFinish(false, err); emit uploadFinish(false, err);
} }
@ -355,6 +355,6 @@ void uploadDiveLogsDE::uploadErrorSlot(QNetworkReply::NetworkError error)
} }
cleanupTempFile(); cleanupTempFile();
QString err(tr("network error %1").arg(error)); QString err(tr("network error %1").arg(error));
report_error(err.toUtf8()); report_error("%s", qPrintable(err));
emit uploadFinish(false, err); emit uploadFinish(false, err);
} }

View file

@ -100,7 +100,7 @@ void uploadDiveShare::uploadTimeoutSlot()
reply = NULL; reply = NULL;
} }
QString err(tr("dive-share.com not responding")); QString err(tr("dive-share.com not responding"));
report_error(err.toUtf8()); report_error("%s", qPrintable(err));
emit uploadFinish(false, err, QByteArray()); emit uploadFinish(false, err, QByteArray());
} }
@ -113,6 +113,6 @@ void uploadDiveShare::uploadErrorSlot(QNetworkReply::NetworkError error)
reply = NULL; reply = NULL;
} }
QString err(tr("network error %1").arg(error)); QString err(tr("network error %1").arg(error));
report_error(err.toUtf8()); report_error("%s", qPrintable(err));
emit uploadFinish(false, err, QByteArray()); emit uploadFinish(false, err, QByteArray());
} }

View file

@ -90,11 +90,11 @@ void VideoFrameExtractor::processItem(QString originalFilename, QString filename
// Since we couldn't sart ffmpeg, turn off thumbnailing // Since we couldn't sart ffmpeg, turn off thumbnailing
// TODO: call the proper preferences-functions // TODO: call the proper preferences-functions
prefs.extract_video_thumbnails = false; prefs.extract_video_thumbnails = false;
report_error(qPrintable(tr("ffmpeg failed to start - video thumbnail creation suspended. To enable video thumbnailing, set working executable in preferences."))); report_error("%s", qPrintable(tr("ffmpeg failed to start - video thumbnail creation suspended. To enable video thumbnailing, set working executable in preferences.")));
return fail(originalFilename, duration, false); return fail(originalFilename, duration, false);
} }
if (!ffmpeg.waitForFinished()) { if (!ffmpeg.waitForFinished()) {
report_error(qPrintable(tr("Failed waiting for ffmpeg - video thumbnail creation suspended. To enable video thumbnailing, set working executable in preferences."))); report_error("%s", qPrintable(tr("Failed waiting for ffmpeg - video thumbnail creation suspended. To enable video thumbnailing, set working executable in preferences.")));
return fail(originalFilename, duration, false); return fail(originalFilename, duration, false);
} }

View file

@ -884,7 +884,7 @@ void DiveListView::loadImagesFromURLs(const QString &urls)
if (image.isNull()) { if (image.isNull()) {
// If this is not an image, maybe it's an html file and Miika can provide some xslr magic to extract images. // If this is not an image, maybe it's an html file and Miika can provide some xslr magic to extract images.
// In this case we would call the function recursively on the list of image source urls; // In this case we would call the function recursively on the list of image source urls;
report_error(qPrintable(tr("%1 does not appear to be an image").arg(url.toString()))); report_error("%s", qPrintable(tr("%1 does not appear to be an image").arg(url.toString())));
return; return;
} }

View file

@ -427,7 +427,7 @@ void MainWindow::on_actionCloudstorageopen_triggered()
static bool saveToCloudOK() static bool saveToCloudOK()
{ {
if (!divelog.dives->nr) { if (!divelog.dives->nr) {
report_error(qPrintable(gettextFromC::tr("Don't save an empty log to the cloud"))); report_error("%s", qPrintable(gettextFromC::tr("Don't save an empty log to the cloud")));
return false; return false;
} }
return true; return true;
@ -486,7 +486,7 @@ void MainWindow::on_actionCloudOnline_triggered()
on_actionCloudstorageopen_triggered(); on_actionCloudstorageopen_triggered();
} }
if (git_local_only) if (git_local_only)
report_error(qPrintable(tr("Failure taking cloud storage online"))); report_error("%s", qPrintable(tr("Failure taking cloud storage online")));
} }
setTitle(); setTitle();

View file

@ -242,7 +242,7 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, int flags)
qDebug() << "Profile calculation for dive " << d->number << "took" << elapsedTime << "ms" << " -- calculated ceiling preference is" << prefs.calcceiling; qDebug() << "Profile calculation for dive " << d->number << "took" << elapsedTime << "ms" << " -- calculated ceiling preference is" << prefs.calcceiling;
if (elapsedTime > 1000 && prefs.calcndltts) { if (elapsedTime > 1000 && prefs.calcndltts) {
qPrefTechnicalDetails::set_calcndltts(false); qPrefTechnicalDetails::set_calcndltts(false);
report_error(qPrintable(tr("Show NDL / TTS was disabled because of excessive processing time"))); report_error("%s", qPrintable(tr("Show NDL / TTS was disabled because of excessive processing time")));
} }
} }