From 5c19c4765f440b53207e442c24eac3d0ba440d64 Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Fri, 1 Sep 2023 18:16:05 +0000 Subject: [PATCH] Deploy mate-desktop/libmateweather to github.com/mate-desktop/libmateweather.git:gh-pages --- .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 133 + .../report-0d7031.html | 1000 +++++++ .../report-1b914f.html | 1029 ++++++++ .../report-20fe9d.html | 944 +++++++ .../report-339c98.html | 1029 ++++++++ .../report-3d7553.html | 775 ++++++ .../report-54e1e1.html | 1245 +++++++++ .../report-688a74.html | 1029 ++++++++ .../report-72c2f8.html | 2352 +++++++++++++++++ .../report-9ba4eb.html | 1266 +++++++++ .../report-9e62c0.html | 2352 +++++++++++++++++ .../report-d766a0.html | 1245 +++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ .../0.html | 1435 ++++++++++ .../1.html | 609 +++++ .../index.html | 201 ++ .../stats.html | 170 ++ .../style.css | 177 ++ CNAME | 1 + index.html | 46 + 192 files changed, 175497 insertions(+) create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/index.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-0d7031.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-1b914f.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-20fe9d.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-339c98.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-3d7553.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-54e1e1.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-688a74.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-72c2f8.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-9ba4eb.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-9e62c0.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-d766a0.html create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/scanview.css create mode 100644 2022-08-06-151824-6014-1@ed1c0813ef0b_master/sorttable.js create mode 100644 2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/0.html create mode 100644 2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/1.html create mode 100644 2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/index.html create mode 100644 2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/stats.html create mode 100644 2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/style.css create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/index.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-0d7031.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-1b914f.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-20fe9d.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-339c98.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-3d7553.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-54e1e1.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-688a74.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-72c2f8.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-9ba4eb.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-9e62c0.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-d766a0.html create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/scanview.css create mode 100644 2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/sorttable.js create mode 100644 2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/0.html create mode 100644 2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/1.html create mode 100644 2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/index.html create mode 100644 2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/stats.html create mode 100644 2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/style.css create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/index.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-0d7031.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-1b914f.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-20fe9d.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-339c98.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-3d7553.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-54e1e1.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-688a74.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-72c2f8.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-9ba4eb.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-9e62c0.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-d766a0.html create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/scanview.css create mode 100644 2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/sorttable.js create mode 100644 2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/0.html create mode 100644 2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/1.html create mode 100644 2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/index.html create mode 100644 2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/stats.html create mode 100644 2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/style.css create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/index.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-0d7031.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-1b914f.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-20fe9d.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-339c98.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-3d7553.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-54e1e1.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-688a74.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-72c2f8.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-9ba4eb.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-9e62c0.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/report-d766a0.html create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/scanview.css create mode 100644 2023-01-13-201344-5870-1@7b60a3282eb7_master/sorttable.js create mode 100644 2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/0.html create mode 100644 2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/1.html create mode 100644 2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/index.html create mode 100644 2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/stats.html create mode 100644 2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/style.css create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/index.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-0d7031.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-1b914f.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-20fe9d.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-339c98.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-3d7553.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-54e1e1.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-688a74.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-72c2f8.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-9ba4eb.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-9e62c0.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/report-d766a0.html create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/scanview.css create mode 100644 2023-01-14-073001-5875-1@f0d464f25291_master/sorttable.js create mode 100644 2023-01-14-073101-4761-cppcheck@f0d464f25291_master/0.html create mode 100644 2023-01-14-073101-4761-cppcheck@f0d464f25291_master/1.html create mode 100644 2023-01-14-073101-4761-cppcheck@f0d464f25291_master/index.html create mode 100644 2023-01-14-073101-4761-cppcheck@f0d464f25291_master/stats.html create mode 100644 2023-01-14-073101-4761-cppcheck@f0d464f25291_master/style.css create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/index.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-0d7031.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-1b914f.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-20fe9d.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-339c98.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-3d7553.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-54e1e1.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-688a74.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-72c2f8.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-9ba4eb.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-9e62c0.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-d766a0.html create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/scanview.css create mode 100644 2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/sorttable.js create mode 100644 2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/0.html create mode 100644 2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/1.html create mode 100644 2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/index.html create mode 100644 2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/stats.html create mode 100644 2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/style.css create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/index.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-0d7031.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-1b914f.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-20fe9d.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-339c98.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-3d7553.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-54e1e1.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-688a74.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-72c2f8.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-9ba4eb.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-9e62c0.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-d766a0.html create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/scanview.css create mode 100644 2023-04-15-095244-5866-1@9b7c8d11cfb4_master/sorttable.js create mode 100644 2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/0.html create mode 100644 2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/1.html create mode 100644 2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/index.html create mode 100644 2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/stats.html create mode 100644 2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/style.css create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/index.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-0d7031.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-1b914f.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-20fe9d.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-339c98.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-3d7553.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-54e1e1.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-688a74.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-72c2f8.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-9ba4eb.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-9e62c0.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/report-d766a0.html create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/scanview.css create mode 100644 2023-07-31-104215-5868-1@df02377275b1_master/sorttable.js create mode 100644 2023-07-31-104317-7452-cppcheck@df02377275b1_master/0.html create mode 100644 2023-07-31-104317-7452-cppcheck@df02377275b1_master/1.html create mode 100644 2023-07-31-104317-7452-cppcheck@df02377275b1_master/index.html create mode 100644 2023-07-31-104317-7452-cppcheck@df02377275b1_master/stats.html create mode 100644 2023-07-31-104317-7452-cppcheck@df02377275b1_master/style.css create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/index.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-0d7031.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-1b914f.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-20fe9d.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-339c98.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-3d7553.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-54e1e1.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-688a74.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-72c2f8.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-9ba4eb.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-9e62c0.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-d766a0.html create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/scanview.css create mode 100644 2023-09-01-180813-5854-1@e4cb5aac0a7c_master/sorttable.js create mode 100644 2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/0.html create mode 100644 2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/1.html create mode 100644 2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/index.html create mode 100644 2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/stats.html create mode 100644 2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/style.css create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/index.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-0d7031.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-1b914f.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-20fe9d.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-339c98.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-3d7553.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-54e1e1.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-688a74.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-72c2f8.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-9ba4eb.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-9e62c0.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/report-d766a0.html create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/scanview.css create mode 100644 2023-09-01-181303-5846-1@58a183825058_master/sorttable.js create mode 100644 2023-09-01-181404-7605-cppcheck@58a183825058_master/0.html create mode 100644 2023-09-01-181404-7605-cppcheck@58a183825058_master/1.html create mode 100644 2023-09-01-181404-7605-cppcheck@58a183825058_master/index.html create mode 100644 2023-09-01-181404-7605-cppcheck@58a183825058_master/stats.html create mode 100644 2023-09-01-181404-7605-cppcheck@58a183825058_master/style.css create mode 100644 CNAME create mode 100644 index.html diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/index.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/index.html new file mode 100644 index 00000000..e61e4387 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@3dff69935e7a
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 14.0.0 (Fedora 14.0.0-1.fc36) +
Date:Sat Aug 6 15:18:24 2022
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-0d7031.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-0d7031.html new file mode 100644 index 00000000..a289c5e1 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-1b914f.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-1b914f.html new file mode 100644 index 00000000..d0ef9052 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-20fe9d.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-20fe9d.html new file mode 100644 index 00000000..b67cd923 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-339c98.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-339c98.html new file mode 100644 index 00000000..7a15debb --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-3d7553.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-3d7553.html new file mode 100644 index 00000000..e6883c1b --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-54e1e1.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-54e1e1.html new file mode 100644 index 00000000..964477c4 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-688a74.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-688a74.html new file mode 100644 index 00000000..ca8cad82 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-72c2f8.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-72c2f8.html new file mode 100644 index 00000000..d1c4e54b --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-9ba4eb.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-9ba4eb.html new file mode 100644 index 00000000..1619c091 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-9e62c0.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-9e62c0.html new file mode 100644 index 00000000..c4f09d2f --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-d766a0.html b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-d766a0.html new file mode 100644 index 00000000..d1b57365 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/14.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-08-06-151824-6014-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/scanview.css b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2022-08-06-151824-6014-1@ed1c0813ef0b_master/sorttable.js b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2022-08-06-151824-6014-1@ed1c0813ef0b_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+
+
+ +
+ + diff --git a/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/1.html b/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/1.html new file mode 100644 index 00000000..7fe6e093 --- /dev/null +++ b/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+
+
+ +
+ + diff --git a/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/index.html b/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/index.html new file mode 100644 index 00000000..161d6410 --- /dev/null +++ b/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/stats.html b/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/stats.html new file mode 100644 index 00000000..431fd75b --- /dev/null +++ b/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/style.css b/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2022-08-06-151927-1393-cppcheck@ed1c0813ef0b_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/index.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/index.html new file mode 100644 index 00000000..35be33de --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@53161c965ac0
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 15.0.6 (Fedora 15.0.6-3.fc37) +
Date:Wed Jan 11 19:57:39 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-0d7031.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-0d7031.html new file mode 100644 index 00000000..0a559c33 --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-1b914f.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-1b914f.html new file mode 100644 index 00000000..806242eb --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-20fe9d.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-20fe9d.html new file mode 100644 index 00000000..677a7faf --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-339c98.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-339c98.html new file mode 100644 index 00000000..1cf4e207 --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-3d7553.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-3d7553.html new file mode 100644 index 00000000..a25f0090 --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-54e1e1.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-54e1e1.html new file mode 100644 index 00000000..7fe0be2d --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-688a74.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-688a74.html new file mode 100644 index 00000000..24376879 --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-72c2f8.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-72c2f8.html new file mode 100644 index 00000000..53f4a33a --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-9ba4eb.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-9ba4eb.html new file mode 100644 index 00000000..7fab6b53 --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-9e62c0.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-9e62c0.html new file mode 100644 index 00000000..76979c11 --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-d766a0.html b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-d766a0.html new file mode 100644 index 00000000..c2e32a76 --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-11-195739-5875-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/scanview.css b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/sorttable.js b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-01-11-195739-5875-1@7a25ec0d46d9_fix-build/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/1.html b/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/1.html new file mode 100644 index 00000000..8fd2afe3 --- /dev/null +++ b/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/index.html b/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/stats.html b/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/style.css b/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-01-11-195837-8067-cppcheck@7a25ec0d46d9_fix-build/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/index.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/index.html new file mode 100644 index 00000000..ee462a10 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@b5d9cbf3d097
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 15.0.6 (Fedora 15.0.6-3.fc37) +
Date:Thu Jan 12 06:06:12 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-0d7031.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-0d7031.html new file mode 100644 index 00000000..b6ad7716 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-1b914f.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-1b914f.html new file mode 100644 index 00000000..dc9737fe --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-20fe9d.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-20fe9d.html new file mode 100644 index 00000000..a93cfb8f --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-339c98.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-339c98.html new file mode 100644 index 00000000..1ce10b37 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-3d7553.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-3d7553.html new file mode 100644 index 00000000..acf18efd --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-54e1e1.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-54e1e1.html new file mode 100644 index 00000000..acd5dae9 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-688a74.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-688a74.html new file mode 100644 index 00000000..850baac9 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-72c2f8.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-72c2f8.html new file mode 100644 index 00000000..dd24db46 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-9ba4eb.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-9ba4eb.html new file mode 100644 index 00000000..66747ac5 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-9e62c0.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-9e62c0.html new file mode 100644 index 00000000..2394743a --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-d766a0.html b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-d766a0.html new file mode 100644 index 00000000..a7086b02 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-12-060612-5877-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/scanview.css b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/sorttable.js b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-01-12-060612-5877-1@a61542ffc2d3_fix-build/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/1.html b/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/1.html new file mode 100644 index 00000000..8fd2afe3 --- /dev/null +++ b/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/index.html b/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/stats.html b/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/style.css b/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-01-12-060711-0102-cppcheck@a61542ffc2d3_fix-build/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/index.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/index.html new file mode 100644 index 00000000..21a792fd --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@855a9e99dee3
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 15.0.6 (Fedora 15.0.6-3.fc37) +
Date:Fri Jan 13 20:13:44 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-0d7031.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-0d7031.html new file mode 100644 index 00000000..d094c0bf --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-1b914f.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-1b914f.html new file mode 100644 index 00000000..a8fce866 --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-20fe9d.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-20fe9d.html new file mode 100644 index 00000000..e7eb2443 --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-339c98.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-339c98.html new file mode 100644 index 00000000..90231e62 --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-3d7553.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-3d7553.html new file mode 100644 index 00000000..694f0ae1 --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-54e1e1.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-54e1e1.html new file mode 100644 index 00000000..347390bd --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-688a74.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-688a74.html new file mode 100644 index 00000000..be9c7a20 --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-72c2f8.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-72c2f8.html new file mode 100644 index 00000000..32bbf6f7 --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-9ba4eb.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-9ba4eb.html new file mode 100644 index 00000000..664e1cca --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-9e62c0.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-9e62c0.html new file mode 100644 index 00000000..9a3e9f4b --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-d766a0.html b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-d766a0.html new file mode 100644 index 00000000..d231a9b4 --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-13-201344-5870-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/scanview.css b/2023-01-13-201344-5870-1@7b60a3282eb7_master/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-01-13-201344-5870-1@7b60a3282eb7_master/sorttable.js b/2023-01-13-201344-5870-1@7b60a3282eb7_master/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-01-13-201344-5870-1@7b60a3282eb7_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/1.html b/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/1.html new file mode 100644 index 00000000..8fd2afe3 --- /dev/null +++ b/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/index.html b/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/stats.html b/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/style.css b/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-01-13-201444-7149-cppcheck@7b60a3282eb7_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/index.html b/2023-01-14-073001-5875-1@f0d464f25291_master/index.html new file mode 100644 index 00000000..b228eb41 --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@425615fda451
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 15.0.6 (Fedora 15.0.6-3.fc37) +
Date:Sat Jan 14 07:30:01 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-0d7031.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-0d7031.html new file mode 100644 index 00000000..fad8f9d8 --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-1b914f.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-1b914f.html new file mode 100644 index 00000000..b94da783 --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-20fe9d.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-20fe9d.html new file mode 100644 index 00000000..af627deb --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-339c98.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-339c98.html new file mode 100644 index 00000000..a895a8f0 --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-3d7553.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-3d7553.html new file mode 100644 index 00000000..f1927dc6 --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-54e1e1.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-54e1e1.html new file mode 100644 index 00000000..a933d358 --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-688a74.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-688a74.html new file mode 100644 index 00000000..0e4153fe --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-72c2f8.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-72c2f8.html new file mode 100644 index 00000000..eb5dc43f --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-9ba4eb.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-9ba4eb.html new file mode 100644 index 00000000..afc10a36 --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-9e62c0.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-9e62c0.html new file mode 100644 index 00000000..f28fcb0c --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/report-d766a0.html b/2023-01-14-073001-5875-1@f0d464f25291_master/report-d766a0.html new file mode 100644 index 00000000..455a2d4b --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.6 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-01-14-073001-5875-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/scanview.css b/2023-01-14-073001-5875-1@f0d464f25291_master/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-01-14-073001-5875-1@f0d464f25291_master/sorttable.js b/2023-01-14-073001-5875-1@f0d464f25291_master/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-01-14-073001-5875-1@f0d464f25291_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/1.html b/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/1.html new file mode 100644 index 00000000..8fd2afe3 --- /dev/null +++ b/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/index.html b/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/stats.html b/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/style.css b/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-01-14-073101-4761-cppcheck@f0d464f25291_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/index.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/index.html new file mode 100644 index 00000000..8ccd03d4 --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@888d89d970fc
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 15.0.7 (Fedora 15.0.7-2.fc37) +
Date:Sat Apr 15 08:55:09 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-0d7031.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-0d7031.html new file mode 100644 index 00000000..b2adaedf --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-1b914f.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-1b914f.html new file mode 100644 index 00000000..b5dfa53c --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-20fe9d.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-20fe9d.html new file mode 100644 index 00000000..26146d45 --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-339c98.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-339c98.html new file mode 100644 index 00000000..bbb3c952 --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-3d7553.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-3d7553.html new file mode 100644 index 00000000..b6af7d4f --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-54e1e1.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-54e1e1.html new file mode 100644 index 00000000..9dfd8a46 --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-688a74.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-688a74.html new file mode 100644 index 00000000..1d6f9252 --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-72c2f8.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-72c2f8.html new file mode 100644 index 00000000..2e81f5cc --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-9ba4eb.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-9ba4eb.html new file mode 100644 index 00000000..829b9112 --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-9e62c0.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-9e62c0.html new file mode 100644 index 00000000..dedf2ce9 --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-d766a0.html b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-d766a0.html new file mode 100644 index 00000000..71eacd2e --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-085509-5864-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/scanview.css b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/sorttable.js b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-04-15-085509-5864-1@d1e1b1d5ea6f_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/1.html b/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/1.html new file mode 100644 index 00000000..8fd2afe3 --- /dev/null +++ b/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/index.html b/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/stats.html b/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/style.css b/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-04-15-085608-2935-cppcheck@d1e1b1d5ea6f_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/index.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/index.html new file mode 100644 index 00000000..3cc660fa --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@fd501bb69aae
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 15.0.7 (Fedora 15.0.7-2.fc37) +
Date:Sat Apr 15 09:52:44 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-0d7031.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-0d7031.html new file mode 100644 index 00000000..c949fa3e --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-1b914f.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-1b914f.html new file mode 100644 index 00000000..fb666efb --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-20fe9d.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-20fe9d.html new file mode 100644 index 00000000..0829782a --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (meto != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (p != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (rp != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-339c98.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-339c98.html new file mode 100644 index 00000000..975465ad --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-3d7553.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-3d7553.html new file mode 100644 index 00000000..66f5f9ae --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-54e1e1.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-54e1e1.html new file mode 100644 index 00000000..a763cdbb --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-688a74.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-688a74.html new file mode 100644 index 00000000..86e04af7 --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-72c2f8.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-72c2f8.html new file mode 100644 index 00000000..ad1ee776 --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-9ba4eb.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-9ba4eb.html new file mode 100644 index 00000000..d4247964 --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-9e62c0.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-9e62c0.html new file mode 100644 index 00000000..5d31d134 --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_; if (
(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name);
135 location->code = g_strdup (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone);
139 } else {
140 location->zone = g_strdup ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar);
145 } else {
146 location->radar = g_strdup ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code);
182 location->tz_hint = g_strdup (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (location != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (prefs != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info->location != ((void*)0)) _g_boolean_var_ = 1; else
_g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info && info->location) _g_boolean_var_ = 1;
else _g_boolean_var_ = 0; _g_boolean_var_; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info && info->location"); return (((void*)0))
; } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed")(mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (sky != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phenomenon != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (qualifier != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (speed != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (direction != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (value != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (phases != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-d766a0.html b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-d766a0.html new file mode 100644 index 00000000..299e6847 --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-15-095244-5866-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (metar != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_
; if (info != ((void*)0)) _g_boolean_var_ = 1; else _g_boolean_var_
= 0; _g_boolean_var_; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/scanview.css b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/sorttable.js b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-04-15-095244-5866-1@9b7c8d11cfb4_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/1.html b/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/1.html new file mode 100644 index 00000000..8fd2afe3 --- /dev/null +++ b/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/index.html b/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/stats.html b/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/style.css b/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-04-15-095343-9847-cppcheck@9b7c8d11cfb4_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/index.html b/2023-07-31-104215-5868-1@df02377275b1_master/index.html new file mode 100644 index 00000000..5494aedc --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@1765e7e2d933
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 16.0.6 (Fedora 16.0.6-2.fc38) +
Date:Mon Jul 31 10:42:15 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-0d7031.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-0d7031.html new file mode 100644 index 00000000..e89b3e0d --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n")g_strdup_inline ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (meto != ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (p != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (rp != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (info != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-1b914f.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-1b914f.html new file mode 100644 index 00000000..ac3e1691 --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_12
; if (info != ((void*)0)) _g_boolean_var_12 = 1; else _g_boolean_var_12
= 0; _g_boolean_var_12; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-20fe9d.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-20fe9d.html new file mode 100644 index 00000000..5d717353 --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n")g_strdup_inline ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_14
; if (meto != ((void*)0)) _g_boolean_var_14 = 1; else _g_boolean_var_14
= 0; _g_boolean_var_14; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_15
; if (p != ((void*)0)) _g_boolean_var_15 = 1; else _g_boolean_var_15
= 0; _g_boolean_var_15; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (rp != ((void*)0)) _g_boolean_var_16 = 1; else _g_boolean_var_16
= 0; _g_boolean_var_16; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (info != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-339c98.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-339c98.html new file mode 100644 index 00000000..e006dd5e --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_11
; if (info != ((void*)0)) _g_boolean_var_11 = 1; else _g_boolean_var_11
= 0; _g_boolean_var_11; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-3d7553.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-3d7553.html new file mode 100644 index 00000000..e781f3ff --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-54e1e1.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-54e1e1.html new file mode 100644 index 00000000..027099f4 --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (info != ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (metar != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (info != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (info != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-688a74.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-688a74.html new file mode 100644 index 00000000..2c19bf03 --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_13
; if (info != ((void*)0)) _g_boolean_var_13 = 1; else _g_boolean_var_13
= 0; _g_boolean_var_13; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-72c2f8.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-72c2f8.html new file mode 100644 index 00000000..bf247236 --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_79; if
((__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_79 = 1; else _g_boolean_var_79 = 0; _g_boolean_var_79
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name)g_strdup_inline (name);
135 location->code = g_strdup (code)g_strdup_inline (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone)g_strdup_inline (zone);
139 } else {
140 location->zone = g_strdup ("------")g_strdup_inline ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar)g_strdup_inline (radar);
145 } else {
146 location->radar = g_strdup ("---")g_strdup_inline ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates)g_strdup_inline (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---")g_strdup_inline ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code)g_strdup_inline (country_code);
182 location->tz_hint = g_strdup (tz_hint)g_strdup_inline (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_80
; if (location != ((void*)0)) _g_boolean_var_80 = 1; else _g_boolean_var_80
= 0; _g_boolean_var_80; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_81 = 1; else _g_boolean_var_81 = 0; _g_boolean_var_81
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_81 = 1; else _g_boolean_var_81 = 0; _g_boolean_var_81
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_82
; if (prefs != ((void*)0)) _g_boolean_var_82 = 1; else _g_boolean_var_82
= 0; _g_boolean_var_82; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url)g_strdup_inline (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_83
; if (info != ((void*)0)) _g_boolean_var_83 = 1; else _g_boolean_var_83
= 0; _g_boolean_var_83; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_84
; if (info != ((void*)0)) _g_boolean_var_84 = 1; else _g_boolean_var_84
= 0; _g_boolean_var_84; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast)g_strdup_inline (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url)g_strdup_inline (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_85
; if (info != ((void*)0)) _g_boolean_var_85 = 1; else _g_boolean_var_85
= 0; _g_boolean_var_85; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_86
; if (info != ((void*)0)) _g_boolean_var_86 = 1; else _g_boolean_var_86
= 0; _g_boolean_var_86; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_87
; if (info != ((void*)0)) _g_boolean_var_87 = 1; else _g_boolean_var_87
= 0; _g_boolean_var_87; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_88
; if (info != ((void*)0)) _g_boolean_var_88 = 1; else _g_boolean_var_88
= 0; _g_boolean_var_88; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_89
; if (info != ((void*)0)) _g_boolean_var_89 = 1; else _g_boolean_var_89
= 0; _g_boolean_var_89; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_90
; if (info != ((void*)0)) _g_boolean_var_90 = 1; else _g_boolean_var_90
= 0; _g_boolean_var_90; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_91
; if (info->location != ((void*)0)) _g_boolean_var_91 = 1;
else _g_boolean_var_91 = 0; _g_boolean_var_91; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info->location != NULL"); return (((void*)0)); } } while
(0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_92
; if (info != ((void*)0)) _g_boolean_var_92 = 1; else _g_boolean_var_92
= 0; _g_boolean_var_92; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
; if (info != ((void*)0)) _g_boolean_var_93 = 1; else _g_boolean_var_93
= 0; _g_boolean_var_93; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_94
; if (info != ((void*)0)) _g_boolean_var_94 = 1; else _g_boolean_var_94
= 0; _g_boolean_var_94; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_95
; if (info != ((void*)0)) _g_boolean_var_95 = 1; else _g_boolean_var_95
= 0; _g_boolean_var_95; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_96
; if (info != ((void*)0)) _g_boolean_var_96 = 1; else _g_boolean_var_96
= 0; _g_boolean_var_96; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_97
; if (info != ((void*)0)) _g_boolean_var_97 = 1; else _g_boolean_var_97
= 0; _g_boolean_var_97; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_98
; if (info != ((void*)0)) _g_boolean_var_98 = 1; else _g_boolean_var_98
= 0; _g_boolean_var_98; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_99
; if (info != ((void*)0)) _g_boolean_var_99 = 1; else _g_boolean_var_99
= 0; _g_boolean_var_99; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
; if (info != ((void*)0)) _g_boolean_var_100 = 1; else _g_boolean_var_100
= 0; _g_boolean_var_100; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (info != ((void*)0)) _g_boolean_var_101 = 1; else _g_boolean_var_101
= 0; _g_boolean_var_101; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_102
; if (info != ((void*)0)) _g_boolean_var_102 = 1; else _g_boolean_var_102
= 0; _g_boolean_var_102; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_103
; if (info != ((void*)0)) _g_boolean_var_103 = 1; else _g_boolean_var_103
= 0; _g_boolean_var_103; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if (info && info->location) _g_boolean_var_104 =
1; else _g_boolean_var_104 = 0; _g_boolean_var_104; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if (info && info->location) _g_boolean_var_105 =
1; else _g_boolean_var_105 = 0; _g_boolean_var_105; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if (info != ((void*)0)) _g_boolean_var_106 = 1; else _g_boolean_var_106
= 0; _g_boolean_var_106; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if (info != ((void*)0)) _g_boolean_var_107 = 1; else _g_boolean_var_107
= 0; _g_boolean_var_107; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if (info != ((void*)0)) _g_boolean_var_108 = 1; else _g_boolean_var_108
= 0; _g_boolean_var_108; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if (info != ((void*)0)) _g_boolean_var_109 = 1; else _g_boolean_var_109
= 0; _g_boolean_var_109; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if (info != ((void*)0)) _g_boolean_var_110 = 1; else _g_boolean_var_110
= 0; _g_boolean_var_110; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed"))g_strdup_inline ((mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if (info != ((void*)0)) _g_boolean_var_111 = 1; else _g_boolean_var_111
= 0; _g_boolean_var_111; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if (info != ((void*)0)) _g_boolean_var_112 = 1; else _g_boolean_var_112
= 0; _g_boolean_var_112; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if (sky != ((void*)0)) _g_boolean_var_113 = 1; else _g_boolean_var_113
= 0; _g_boolean_var_113; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if (info != ((void*)0)) _g_boolean_var_114 = 1; else _g_boolean_var_114
= 0; _g_boolean_var_114; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if (phenomenon != ((void*)0)) _g_boolean_var_115 = 1; else _g_boolean_var_115
= 0; _g_boolean_var_115; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if (qualifier != ((void*)0)) _g_boolean_var_116 = 1; else _g_boolean_var_116
= 0; _g_boolean_var_116; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if (info != ((void*)0)) _g_boolean_var_117 = 1; else _g_boolean_var_117
= 0; _g_boolean_var_117; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if (value != ((void*)0)) _g_boolean_var_118 = 1; else _g_boolean_var_118
= 0; _g_boolean_var_118; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if (info != ((void*)0)) _g_boolean_var_119 = 1; else _g_boolean_var_119
= 0; _g_boolean_var_119; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (value != ((void*)0)) _g_boolean_var_120 = 1; else _g_boolean_var_120
= 0; _g_boolean_var_120; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if (info != ((void*)0)) _g_boolean_var_121 = 1; else _g_boolean_var_121
= 0; _g_boolean_var_121; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if (value != ((void*)0)) _g_boolean_var_122 = 1; else _g_boolean_var_122
= 0; _g_boolean_var_122; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if (info != ((void*)0)) _g_boolean_var_123 = 1; else _g_boolean_var_123
= 0; _g_boolean_var_123; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if (value != ((void*)0)) _g_boolean_var_124 = 1; else _g_boolean_var_124
= 0; _g_boolean_var_124; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if (info != ((void*)0)) _g_boolean_var_125 = 1; else _g_boolean_var_125
= 0; _g_boolean_var_125; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if (value != ((void*)0)) _g_boolean_var_126 = 1; else _g_boolean_var_126
= 0; _g_boolean_var_126; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if (info != ((void*)0)) _g_boolean_var_127 = 1; else _g_boolean_var_127
= 0; _g_boolean_var_127; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if (value != ((void*)0)) _g_boolean_var_128 = 1; else _g_boolean_var_128
= 0; _g_boolean_var_128; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if (info != ((void*)0)) _g_boolean_var_129 = 1; else _g_boolean_var_129
= 0; _g_boolean_var_129; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if (value != ((void*)0)) _g_boolean_var_130 = 1; else _g_boolean_var_130
= 0; _g_boolean_var_130; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if (info != ((void*)0)) _g_boolean_var_131 = 1; else _g_boolean_var_131
= 0; _g_boolean_var_131; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_132
; if (value != ((void*)0)) _g_boolean_var_132 = 1; else _g_boolean_var_132
= 0; _g_boolean_var_132; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if (info != ((void*)0)) _g_boolean_var_133 = 1; else _g_boolean_var_133
= 0; _g_boolean_var_133; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (value != ((void*)0)) _g_boolean_var_134 = 1; else _g_boolean_var_134
= 0; _g_boolean_var_134; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if (info != ((void*)0)) _g_boolean_var_135 = 1; else _g_boolean_var_135
= 0; _g_boolean_var_135; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if (speed != ((void*)0)) _g_boolean_var_136 = 1; else _g_boolean_var_136
= 0; _g_boolean_var_136; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if (direction != ((void*)0)) _g_boolean_var_137 = 1; else _g_boolean_var_137
= 0; _g_boolean_var_137; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if (info != ((void*)0)) _g_boolean_var_138 = 1; else _g_boolean_var_138
= 0; _g_boolean_var_138; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if (value != ((void*)0)) _g_boolean_var_139 = 1; else _g_boolean_var_139
= 0; _g_boolean_var_139; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if (info != ((void*)0)) _g_boolean_var_140 = 1; else _g_boolean_var_140
= 0; _g_boolean_var_140; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (value != ((void*)0)) _g_boolean_var_141 = 1; else _g_boolean_var_141
= 0; _g_boolean_var_141; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if (info != ((void*)0)) _g_boolean_var_142 = 1; else _g_boolean_var_142
= 0; _g_boolean_var_142; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if (phases != ((void*)0)) _g_boolean_var_143 = 1; else _g_boolean_var_143
= 0; _g_boolean_var_143; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_144 = 1; else _g_boolean_var_144
= 0; _g_boolean_var_144; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_145 = 1; else _g_boolean_var_145 = 0; _g_boolean_var_145
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_146 = 1; else _g_boolean_var_146
= 0; _g_boolean_var_146; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_147 = 1; else _g_boolean_var_147
= 0; _g_boolean_var_147; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-9ba4eb.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-9ba4eb.html new file mode 100644 index 00000000..3c135830 --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_14
; if (info != ((void*)0)) _g_boolean_var_14 = 1; else _g_boolean_var_14
= 0; _g_boolean_var_14; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_15
; if (metar != ((void*)0)) _g_boolean_var_15 = 1; else _g_boolean_var_15
= 0; _g_boolean_var_15; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (info != ((void*)0)) _g_boolean_var_16 = 1; else _g_boolean_var_16
= 0; _g_boolean_var_16; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (info != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-9e62c0.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-9e62c0.html new file mode 100644 index 00000000..dda06f6e --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_148; if
((__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_148 = 1; else _g_boolean_var_148 = 0; _g_boolean_var_148
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name)g_strdup_inline (name);
135 location->code = g_strdup (code)g_strdup_inline (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone)g_strdup_inline (zone);
139 } else {
140 location->zone = g_strdup ("------")g_strdup_inline ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar)g_strdup_inline (radar);
145 } else {
146 location->radar = g_strdup ("---")g_strdup_inline ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates)g_strdup_inline (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---")g_strdup_inline ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code)g_strdup_inline (country_code);
182 location->tz_hint = g_strdup (tz_hint)g_strdup_inline (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if (location != ((void*)0)) _g_boolean_var_149 = 1; else _g_boolean_var_149
= 0; _g_boolean_var_149; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if (prefs != ((void*)0)) _g_boolean_var_151 = 1; else _g_boolean_var_151
= 0; _g_boolean_var_151; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url)g_strdup_inline (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if (info != ((void*)0)) _g_boolean_var_152 = 1; else _g_boolean_var_152
= 0; _g_boolean_var_152; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if (info != ((void*)0)) _g_boolean_var_153 = 1; else _g_boolean_var_153
= 0; _g_boolean_var_153; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast)g_strdup_inline (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url)g_strdup_inline (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if (info != ((void*)0)) _g_boolean_var_154 = 1; else _g_boolean_var_154
= 0; _g_boolean_var_154; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if (info != ((void*)0)) _g_boolean_var_155 = 1; else _g_boolean_var_155
= 0; _g_boolean_var_155; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if (info != ((void*)0)) _g_boolean_var_156 = 1; else _g_boolean_var_156
= 0; _g_boolean_var_156; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if (info != ((void*)0)) _g_boolean_var_157 = 1; else _g_boolean_var_157
= 0; _g_boolean_var_157; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if (info != ((void*)0)) _g_boolean_var_158 = 1; else _g_boolean_var_158
= 0; _g_boolean_var_158; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if (info != ((void*)0)) _g_boolean_var_159 = 1; else _g_boolean_var_159
= 0; _g_boolean_var_159; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if (info->location != ((void*)0)) _g_boolean_var_160 = 1
; else _g_boolean_var_160 = 0; _g_boolean_var_160; }), 1))) {
} else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info->location != NULL"); return (((void*
)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if (info != ((void*)0)) _g_boolean_var_161 = 1; else _g_boolean_var_161
= 0; _g_boolean_var_161; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if (info != ((void*)0)) _g_boolean_var_162 = 1; else _g_boolean_var_162
= 0; _g_boolean_var_162; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if (info != ((void*)0)) _g_boolean_var_163 = 1; else _g_boolean_var_163
= 0; _g_boolean_var_163; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if (info != ((void*)0)) _g_boolean_var_164 = 1; else _g_boolean_var_164
= 0; _g_boolean_var_164; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if (info != ((void*)0)) _g_boolean_var_165 = 1; else _g_boolean_var_165
= 0; _g_boolean_var_165; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if (info != ((void*)0)) _g_boolean_var_166 = 1; else _g_boolean_var_166
= 0; _g_boolean_var_166; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if (info != ((void*)0)) _g_boolean_var_167 = 1; else _g_boolean_var_167
= 0; _g_boolean_var_167; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if (info != ((void*)0)) _g_boolean_var_168 = 1; else _g_boolean_var_168
= 0; _g_boolean_var_168; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if (info != ((void*)0)) _g_boolean_var_169 = 1; else _g_boolean_var_169
= 0; _g_boolean_var_169; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if (info != ((void*)0)) _g_boolean_var_170 = 1; else _g_boolean_var_170
= 0; _g_boolean_var_170; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_171
; if (info != ((void*)0)) _g_boolean_var_171 = 1; else _g_boolean_var_171
= 0; _g_boolean_var_171; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_172
; if (info != ((void*)0)) _g_boolean_var_172 = 1; else _g_boolean_var_172
= 0; _g_boolean_var_172; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_173
; if (info && info->location) _g_boolean_var_173 =
1; else _g_boolean_var_173 = 0; _g_boolean_var_173; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_174
; if (info && info->location) _g_boolean_var_174 =
1; else _g_boolean_var_174 = 0; _g_boolean_var_174; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_175
; if (info != ((void*)0)) _g_boolean_var_175 = 1; else _g_boolean_var_175
= 0; _g_boolean_var_175; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if (info != ((void*)0)) _g_boolean_var_176 = 1; else _g_boolean_var_176
= 0; _g_boolean_var_176; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_177
; if (info != ((void*)0)) _g_boolean_var_177 = 1; else _g_boolean_var_177
= 0; _g_boolean_var_177; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if (info != ((void*)0)) _g_boolean_var_178 = 1; else _g_boolean_var_178
= 0; _g_boolean_var_178; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if (info != ((void*)0)) _g_boolean_var_179 = 1; else _g_boolean_var_179
= 0; _g_boolean_var_179; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed"))g_strdup_inline ((mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if (info != ((void*)0)) _g_boolean_var_180 = 1; else _g_boolean_var_180
= 0; _g_boolean_var_180; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if (info != ((void*)0)) _g_boolean_var_181 = 1; else _g_boolean_var_181
= 0; _g_boolean_var_181; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if (sky != ((void*)0)) _g_boolean_var_182 = 1; else _g_boolean_var_182
= 0; _g_boolean_var_182; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if (info != ((void*)0)) _g_boolean_var_183 = 1; else _g_boolean_var_183
= 0; _g_boolean_var_183; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (phenomenon != ((void*)0)) _g_boolean_var_184 = 1; else _g_boolean_var_184
= 0; _g_boolean_var_184; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if (qualifier != ((void*)0)) _g_boolean_var_185 = 1; else _g_boolean_var_185
= 0; _g_boolean_var_185; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if (info != ((void*)0)) _g_boolean_var_186 = 1; else _g_boolean_var_186
= 0; _g_boolean_var_186; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if (value != ((void*)0)) _g_boolean_var_187 = 1; else _g_boolean_var_187
= 0; _g_boolean_var_187; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if (info != ((void*)0)) _g_boolean_var_188 = 1; else _g_boolean_var_188
= 0; _g_boolean_var_188; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if (value != ((void*)0)) _g_boolean_var_189 = 1; else _g_boolean_var_189
= 0; _g_boolean_var_189; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if (info != ((void*)0)) _g_boolean_var_190 = 1; else _g_boolean_var_190
= 0; _g_boolean_var_190; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if (value != ((void*)0)) _g_boolean_var_191 = 1; else _g_boolean_var_191
= 0; _g_boolean_var_191; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if (info != ((void*)0)) _g_boolean_var_192 = 1; else _g_boolean_var_192
= 0; _g_boolean_var_192; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if (value != ((void*)0)) _g_boolean_var_193 = 1; else _g_boolean_var_193
= 0; _g_boolean_var_193; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if (info != ((void*)0)) _g_boolean_var_194 = 1; else _g_boolean_var_194
= 0; _g_boolean_var_194; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if (value != ((void*)0)) _g_boolean_var_195 = 1; else _g_boolean_var_195
= 0; _g_boolean_var_195; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if (info != ((void*)0)) _g_boolean_var_196 = 1; else _g_boolean_var_196
= 0; _g_boolean_var_196; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if (value != ((void*)0)) _g_boolean_var_197 = 1; else _g_boolean_var_197
= 0; _g_boolean_var_197; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if (info != ((void*)0)) _g_boolean_var_198 = 1; else _g_boolean_var_198
= 0; _g_boolean_var_198; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if (value != ((void*)0)) _g_boolean_var_199 = 1; else _g_boolean_var_199
= 0; _g_boolean_var_199; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if (info != ((void*)0)) _g_boolean_var_200 = 1; else _g_boolean_var_200
= 0; _g_boolean_var_200; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if (value != ((void*)0)) _g_boolean_var_201 = 1; else _g_boolean_var_201
= 0; _g_boolean_var_201; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (info != ((void*)0)) _g_boolean_var_202 = 1; else _g_boolean_var_202
= 0; _g_boolean_var_202; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if (value != ((void*)0)) _g_boolean_var_203 = 1; else _g_boolean_var_203
= 0; _g_boolean_var_203; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if (info != ((void*)0)) _g_boolean_var_204 = 1; else _g_boolean_var_204
= 0; _g_boolean_var_204; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if (speed != ((void*)0)) _g_boolean_var_205 = 1; else _g_boolean_var_205
= 0; _g_boolean_var_205; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (direction != ((void*)0)) _g_boolean_var_206 = 1; else _g_boolean_var_206
= 0; _g_boolean_var_206; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if (info != ((void*)0)) _g_boolean_var_207 = 1; else _g_boolean_var_207
= 0; _g_boolean_var_207; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if (value != ((void*)0)) _g_boolean_var_208 = 1; else _g_boolean_var_208
= 0; _g_boolean_var_208; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if (info != ((void*)0)) _g_boolean_var_209 = 1; else _g_boolean_var_209
= 0; _g_boolean_var_209; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if (value != ((void*)0)) _g_boolean_var_210 = 1; else _g_boolean_var_210
= 0; _g_boolean_var_210; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if (info != ((void*)0)) _g_boolean_var_211 = 1; else _g_boolean_var_211
= 0; _g_boolean_var_211; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if (phases != ((void*)0)) _g_boolean_var_212 = 1; else _g_boolean_var_212
= 0; _g_boolean_var_212; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_213 = 1; else _g_boolean_var_213
= 0; _g_boolean_var_213; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_214 = 1; else _g_boolean_var_214 = 0; _g_boolean_var_214
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_215 = 1; else _g_boolean_var_215
= 0; _g_boolean_var_215; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_216 = 1; else _g_boolean_var_216
= 0; _g_boolean_var_216; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/report-d766a0.html b/2023-07-31-104215-5868-1@df02377275b1_master/report-d766a0.html new file mode 100644 index 00000000..eaddec76 --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-07-31-104215-5868-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (info != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (metar != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (info != ((void*)0)) _g_boolean_var_24 = 1; else _g_boolean_var_24
= 0; _g_boolean_var_24; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (info != ((void*)0)) _g_boolean_var_25 = 1; else _g_boolean_var_25
= 0; _g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/scanview.css b/2023-07-31-104215-5868-1@df02377275b1_master/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-07-31-104215-5868-1@df02377275b1_master/sorttable.js b/2023-07-31-104215-5868-1@df02377275b1_master/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-07-31-104215-5868-1@df02377275b1_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-07-31-104317-7452-cppcheck@df02377275b1_master/1.html b/2023-07-31-104317-7452-cppcheck@df02377275b1_master/1.html new file mode 100644 index 00000000..95970ba7 --- /dev/null +++ b/2023-07-31-104317-7452-cppcheck@df02377275b1_master/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-07-31-104317-7452-cppcheck@df02377275b1_master/index.html b/2023-07-31-104317-7452-cppcheck@df02377275b1_master/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-07-31-104317-7452-cppcheck@df02377275b1_master/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-07-31-104317-7452-cppcheck@df02377275b1_master/stats.html b/2023-07-31-104317-7452-cppcheck@df02377275b1_master/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-07-31-104317-7452-cppcheck@df02377275b1_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-07-31-104317-7452-cppcheck@df02377275b1_master/style.css b/2023-07-31-104317-7452-cppcheck@df02377275b1_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-07-31-104317-7452-cppcheck@df02377275b1_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/index.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/index.html new file mode 100644 index 00000000..adb44c2d --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@c4eff81e8d07
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 16.0.6 (Fedora 16.0.6-2.fc38) +
Date:Fri Sep 1 18:08:13 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-0d7031.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-0d7031.html new file mode 100644 index 00000000..c7567577 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n")g_strdup_inline ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (meto != ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (p != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (rp != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (info != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-1b914f.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-1b914f.html new file mode 100644 index 00000000..5ae85e67 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_12
; if (info != ((void*)0)) _g_boolean_var_12 = 1; else _g_boolean_var_12
= 0; _g_boolean_var_12; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-20fe9d.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-20fe9d.html new file mode 100644 index 00000000..d925c4ab --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n")g_strdup_inline ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_14
; if (meto != ((void*)0)) _g_boolean_var_14 = 1; else _g_boolean_var_14
= 0; _g_boolean_var_14; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_15
; if (p != ((void*)0)) _g_boolean_var_15 = 1; else _g_boolean_var_15
= 0; _g_boolean_var_15; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (rp != ((void*)0)) _g_boolean_var_16 = 1; else _g_boolean_var_16
= 0; _g_boolean_var_16; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (info != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-339c98.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-339c98.html new file mode 100644 index 00000000..7a46bcd3 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_11
; if (info != ((void*)0)) _g_boolean_var_11 = 1; else _g_boolean_var_11
= 0; _g_boolean_var_11; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-3d7553.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-3d7553.html new file mode 100644 index 00000000..d2faed4b --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-54e1e1.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-54e1e1.html new file mode 100644 index 00000000..fd360526 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (info != ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (metar != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (info != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (info != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-688a74.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-688a74.html new file mode 100644 index 00000000..1927014a --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_13
; if (info != ((void*)0)) _g_boolean_var_13 = 1; else _g_boolean_var_13
= 0; _g_boolean_var_13; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-72c2f8.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-72c2f8.html new file mode 100644 index 00000000..79ab3e23 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_79; if
((__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_79 = 1; else _g_boolean_var_79 = 0; _g_boolean_var_79
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name)g_strdup_inline (name);
135 location->code = g_strdup (code)g_strdup_inline (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone)g_strdup_inline (zone);
139 } else {
140 location->zone = g_strdup ("------")g_strdup_inline ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar)g_strdup_inline (radar);
145 } else {
146 location->radar = g_strdup ("---")g_strdup_inline ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates)g_strdup_inline (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---")g_strdup_inline ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code)g_strdup_inline (country_code);
182 location->tz_hint = g_strdup (tz_hint)g_strdup_inline (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_80
; if (location != ((void*)0)) _g_boolean_var_80 = 1; else _g_boolean_var_80
= 0; _g_boolean_var_80; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_81 = 1; else _g_boolean_var_81 = 0; _g_boolean_var_81
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_81 = 1; else _g_boolean_var_81 = 0; _g_boolean_var_81
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_82
; if (prefs != ((void*)0)) _g_boolean_var_82 = 1; else _g_boolean_var_82
= 0; _g_boolean_var_82; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url)g_strdup_inline (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_83
; if (info != ((void*)0)) _g_boolean_var_83 = 1; else _g_boolean_var_83
= 0; _g_boolean_var_83; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_84
; if (info != ((void*)0)) _g_boolean_var_84 = 1; else _g_boolean_var_84
= 0; _g_boolean_var_84; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast)g_strdup_inline (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url)g_strdup_inline (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_85
; if (info != ((void*)0)) _g_boolean_var_85 = 1; else _g_boolean_var_85
= 0; _g_boolean_var_85; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_86
; if (info != ((void*)0)) _g_boolean_var_86 = 1; else _g_boolean_var_86
= 0; _g_boolean_var_86; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_87
; if (info != ((void*)0)) _g_boolean_var_87 = 1; else _g_boolean_var_87
= 0; _g_boolean_var_87; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_88
; if (info != ((void*)0)) _g_boolean_var_88 = 1; else _g_boolean_var_88
= 0; _g_boolean_var_88; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_89
; if (info != ((void*)0)) _g_boolean_var_89 = 1; else _g_boolean_var_89
= 0; _g_boolean_var_89; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_90
; if (info != ((void*)0)) _g_boolean_var_90 = 1; else _g_boolean_var_90
= 0; _g_boolean_var_90; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_91
; if (info->location != ((void*)0)) _g_boolean_var_91 = 1;
else _g_boolean_var_91 = 0; _g_boolean_var_91; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info->location != NULL"); return (((void*)0)); } } while
(0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_92
; if (info != ((void*)0)) _g_boolean_var_92 = 1; else _g_boolean_var_92
= 0; _g_boolean_var_92; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
; if (info != ((void*)0)) _g_boolean_var_93 = 1; else _g_boolean_var_93
= 0; _g_boolean_var_93; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_94
; if (info != ((void*)0)) _g_boolean_var_94 = 1; else _g_boolean_var_94
= 0; _g_boolean_var_94; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_95
; if (info != ((void*)0)) _g_boolean_var_95 = 1; else _g_boolean_var_95
= 0; _g_boolean_var_95; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_96
; if (info != ((void*)0)) _g_boolean_var_96 = 1; else _g_boolean_var_96
= 0; _g_boolean_var_96; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_97
; if (info != ((void*)0)) _g_boolean_var_97 = 1; else _g_boolean_var_97
= 0; _g_boolean_var_97; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_98
; if (info != ((void*)0)) _g_boolean_var_98 = 1; else _g_boolean_var_98
= 0; _g_boolean_var_98; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_99
; if (info != ((void*)0)) _g_boolean_var_99 = 1; else _g_boolean_var_99
= 0; _g_boolean_var_99; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
; if (info != ((void*)0)) _g_boolean_var_100 = 1; else _g_boolean_var_100
= 0; _g_boolean_var_100; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (info != ((void*)0)) _g_boolean_var_101 = 1; else _g_boolean_var_101
= 0; _g_boolean_var_101; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_102
; if (info != ((void*)0)) _g_boolean_var_102 = 1; else _g_boolean_var_102
= 0; _g_boolean_var_102; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_103
; if (info != ((void*)0)) _g_boolean_var_103 = 1; else _g_boolean_var_103
= 0; _g_boolean_var_103; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if (info && info->location) _g_boolean_var_104 =
1; else _g_boolean_var_104 = 0; _g_boolean_var_104; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if (info && info->location) _g_boolean_var_105 =
1; else _g_boolean_var_105 = 0; _g_boolean_var_105; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if (info != ((void*)0)) _g_boolean_var_106 = 1; else _g_boolean_var_106
= 0; _g_boolean_var_106; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if (info != ((void*)0)) _g_boolean_var_107 = 1; else _g_boolean_var_107
= 0; _g_boolean_var_107; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if (info != ((void*)0)) _g_boolean_var_108 = 1; else _g_boolean_var_108
= 0; _g_boolean_var_108; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if (info != ((void*)0)) _g_boolean_var_109 = 1; else _g_boolean_var_109
= 0; _g_boolean_var_109; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if (info != ((void*)0)) _g_boolean_var_110 = 1; else _g_boolean_var_110
= 0; _g_boolean_var_110; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed"))g_strdup_inline ((mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if (info != ((void*)0)) _g_boolean_var_111 = 1; else _g_boolean_var_111
= 0; _g_boolean_var_111; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if (info != ((void*)0)) _g_boolean_var_112 = 1; else _g_boolean_var_112
= 0; _g_boolean_var_112; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if (sky != ((void*)0)) _g_boolean_var_113 = 1; else _g_boolean_var_113
= 0; _g_boolean_var_113; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if (info != ((void*)0)) _g_boolean_var_114 = 1; else _g_boolean_var_114
= 0; _g_boolean_var_114; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if (phenomenon != ((void*)0)) _g_boolean_var_115 = 1; else _g_boolean_var_115
= 0; _g_boolean_var_115; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if (qualifier != ((void*)0)) _g_boolean_var_116 = 1; else _g_boolean_var_116
= 0; _g_boolean_var_116; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if (info != ((void*)0)) _g_boolean_var_117 = 1; else _g_boolean_var_117
= 0; _g_boolean_var_117; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if (value != ((void*)0)) _g_boolean_var_118 = 1; else _g_boolean_var_118
= 0; _g_boolean_var_118; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if (info != ((void*)0)) _g_boolean_var_119 = 1; else _g_boolean_var_119
= 0; _g_boolean_var_119; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (value != ((void*)0)) _g_boolean_var_120 = 1; else _g_boolean_var_120
= 0; _g_boolean_var_120; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if (info != ((void*)0)) _g_boolean_var_121 = 1; else _g_boolean_var_121
= 0; _g_boolean_var_121; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if (value != ((void*)0)) _g_boolean_var_122 = 1; else _g_boolean_var_122
= 0; _g_boolean_var_122; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if (info != ((void*)0)) _g_boolean_var_123 = 1; else _g_boolean_var_123
= 0; _g_boolean_var_123; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if (value != ((void*)0)) _g_boolean_var_124 = 1; else _g_boolean_var_124
= 0; _g_boolean_var_124; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if (info != ((void*)0)) _g_boolean_var_125 = 1; else _g_boolean_var_125
= 0; _g_boolean_var_125; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if (value != ((void*)0)) _g_boolean_var_126 = 1; else _g_boolean_var_126
= 0; _g_boolean_var_126; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if (info != ((void*)0)) _g_boolean_var_127 = 1; else _g_boolean_var_127
= 0; _g_boolean_var_127; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if (value != ((void*)0)) _g_boolean_var_128 = 1; else _g_boolean_var_128
= 0; _g_boolean_var_128; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if (info != ((void*)0)) _g_boolean_var_129 = 1; else _g_boolean_var_129
= 0; _g_boolean_var_129; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if (value != ((void*)0)) _g_boolean_var_130 = 1; else _g_boolean_var_130
= 0; _g_boolean_var_130; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if (info != ((void*)0)) _g_boolean_var_131 = 1; else _g_boolean_var_131
= 0; _g_boolean_var_131; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_132
; if (value != ((void*)0)) _g_boolean_var_132 = 1; else _g_boolean_var_132
= 0; _g_boolean_var_132; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if (info != ((void*)0)) _g_boolean_var_133 = 1; else _g_boolean_var_133
= 0; _g_boolean_var_133; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (value != ((void*)0)) _g_boolean_var_134 = 1; else _g_boolean_var_134
= 0; _g_boolean_var_134; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if (info != ((void*)0)) _g_boolean_var_135 = 1; else _g_boolean_var_135
= 0; _g_boolean_var_135; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if (speed != ((void*)0)) _g_boolean_var_136 = 1; else _g_boolean_var_136
= 0; _g_boolean_var_136; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if (direction != ((void*)0)) _g_boolean_var_137 = 1; else _g_boolean_var_137
= 0; _g_boolean_var_137; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if (info != ((void*)0)) _g_boolean_var_138 = 1; else _g_boolean_var_138
= 0; _g_boolean_var_138; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if (value != ((void*)0)) _g_boolean_var_139 = 1; else _g_boolean_var_139
= 0; _g_boolean_var_139; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if (info != ((void*)0)) _g_boolean_var_140 = 1; else _g_boolean_var_140
= 0; _g_boolean_var_140; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (value != ((void*)0)) _g_boolean_var_141 = 1; else _g_boolean_var_141
= 0; _g_boolean_var_141; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if (info != ((void*)0)) _g_boolean_var_142 = 1; else _g_boolean_var_142
= 0; _g_boolean_var_142; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if (phases != ((void*)0)) _g_boolean_var_143 = 1; else _g_boolean_var_143
= 0; _g_boolean_var_143; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_144 = 1; else _g_boolean_var_144
= 0; _g_boolean_var_144; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_145 = 1; else _g_boolean_var_145 = 0; _g_boolean_var_145
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_146 = 1; else _g_boolean_var_146
= 0; _g_boolean_var_146; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_147 = 1; else _g_boolean_var_147
= 0; _g_boolean_var_147; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-9ba4eb.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-9ba4eb.html new file mode 100644 index 00000000..b374b611 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_14
; if (info != ((void*)0)) _g_boolean_var_14 = 1; else _g_boolean_var_14
= 0; _g_boolean_var_14; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_15
; if (metar != ((void*)0)) _g_boolean_var_15 = 1; else _g_boolean_var_15
= 0; _g_boolean_var_15; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (info != ((void*)0)) _g_boolean_var_16 = 1; else _g_boolean_var_16
= 0; _g_boolean_var_16; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (info != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-9e62c0.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-9e62c0.html new file mode 100644 index 00000000..8a252555 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_148; if
((__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_148 = 1; else _g_boolean_var_148 = 0; _g_boolean_var_148
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name)g_strdup_inline (name);
135 location->code = g_strdup (code)g_strdup_inline (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone)g_strdup_inline (zone);
139 } else {
140 location->zone = g_strdup ("------")g_strdup_inline ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar)g_strdup_inline (radar);
145 } else {
146 location->radar = g_strdup ("---")g_strdup_inline ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates)g_strdup_inline (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---")g_strdup_inline ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code)g_strdup_inline (country_code);
182 location->tz_hint = g_strdup (tz_hint)g_strdup_inline (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if (location != ((void*)0)) _g_boolean_var_149 = 1; else _g_boolean_var_149
= 0; _g_boolean_var_149; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if (prefs != ((void*)0)) _g_boolean_var_151 = 1; else _g_boolean_var_151
= 0; _g_boolean_var_151; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url)g_strdup_inline (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if (info != ((void*)0)) _g_boolean_var_152 = 1; else _g_boolean_var_152
= 0; _g_boolean_var_152; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if (info != ((void*)0)) _g_boolean_var_153 = 1; else _g_boolean_var_153
= 0; _g_boolean_var_153; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast)g_strdup_inline (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url)g_strdup_inline (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if (info != ((void*)0)) _g_boolean_var_154 = 1; else _g_boolean_var_154
= 0; _g_boolean_var_154; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if (info != ((void*)0)) _g_boolean_var_155 = 1; else _g_boolean_var_155
= 0; _g_boolean_var_155; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if (info != ((void*)0)) _g_boolean_var_156 = 1; else _g_boolean_var_156
= 0; _g_boolean_var_156; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if (info != ((void*)0)) _g_boolean_var_157 = 1; else _g_boolean_var_157
= 0; _g_boolean_var_157; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if (info != ((void*)0)) _g_boolean_var_158 = 1; else _g_boolean_var_158
= 0; _g_boolean_var_158; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if (info != ((void*)0)) _g_boolean_var_159 = 1; else _g_boolean_var_159
= 0; _g_boolean_var_159; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if (info->location != ((void*)0)) _g_boolean_var_160 = 1
; else _g_boolean_var_160 = 0; _g_boolean_var_160; }), 1))) {
} else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info->location != NULL"); return (((void*
)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if (info != ((void*)0)) _g_boolean_var_161 = 1; else _g_boolean_var_161
= 0; _g_boolean_var_161; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if (info != ((void*)0)) _g_boolean_var_162 = 1; else _g_boolean_var_162
= 0; _g_boolean_var_162; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if (info != ((void*)0)) _g_boolean_var_163 = 1; else _g_boolean_var_163
= 0; _g_boolean_var_163; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if (info != ((void*)0)) _g_boolean_var_164 = 1; else _g_boolean_var_164
= 0; _g_boolean_var_164; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if (info != ((void*)0)) _g_boolean_var_165 = 1; else _g_boolean_var_165
= 0; _g_boolean_var_165; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if (info != ((void*)0)) _g_boolean_var_166 = 1; else _g_boolean_var_166
= 0; _g_boolean_var_166; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if (info != ((void*)0)) _g_boolean_var_167 = 1; else _g_boolean_var_167
= 0; _g_boolean_var_167; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if (info != ((void*)0)) _g_boolean_var_168 = 1; else _g_boolean_var_168
= 0; _g_boolean_var_168; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if (info != ((void*)0)) _g_boolean_var_169 = 1; else _g_boolean_var_169
= 0; _g_boolean_var_169; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if (info != ((void*)0)) _g_boolean_var_170 = 1; else _g_boolean_var_170
= 0; _g_boolean_var_170; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_171
; if (info != ((void*)0)) _g_boolean_var_171 = 1; else _g_boolean_var_171
= 0; _g_boolean_var_171; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_172
; if (info != ((void*)0)) _g_boolean_var_172 = 1; else _g_boolean_var_172
= 0; _g_boolean_var_172; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_173
; if (info && info->location) _g_boolean_var_173 =
1; else _g_boolean_var_173 = 0; _g_boolean_var_173; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_174
; if (info && info->location) _g_boolean_var_174 =
1; else _g_boolean_var_174 = 0; _g_boolean_var_174; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_175
; if (info != ((void*)0)) _g_boolean_var_175 = 1; else _g_boolean_var_175
= 0; _g_boolean_var_175; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if (info != ((void*)0)) _g_boolean_var_176 = 1; else _g_boolean_var_176
= 0; _g_boolean_var_176; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_177
; if (info != ((void*)0)) _g_boolean_var_177 = 1; else _g_boolean_var_177
= 0; _g_boolean_var_177; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if (info != ((void*)0)) _g_boolean_var_178 = 1; else _g_boolean_var_178
= 0; _g_boolean_var_178; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if (info != ((void*)0)) _g_boolean_var_179 = 1; else _g_boolean_var_179
= 0; _g_boolean_var_179; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed"))g_strdup_inline ((mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if (info != ((void*)0)) _g_boolean_var_180 = 1; else _g_boolean_var_180
= 0; _g_boolean_var_180; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if (info != ((void*)0)) _g_boolean_var_181 = 1; else _g_boolean_var_181
= 0; _g_boolean_var_181; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if (sky != ((void*)0)) _g_boolean_var_182 = 1; else _g_boolean_var_182
= 0; _g_boolean_var_182; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if (info != ((void*)0)) _g_boolean_var_183 = 1; else _g_boolean_var_183
= 0; _g_boolean_var_183; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (phenomenon != ((void*)0)) _g_boolean_var_184 = 1; else _g_boolean_var_184
= 0; _g_boolean_var_184; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if (qualifier != ((void*)0)) _g_boolean_var_185 = 1; else _g_boolean_var_185
= 0; _g_boolean_var_185; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if (info != ((void*)0)) _g_boolean_var_186 = 1; else _g_boolean_var_186
= 0; _g_boolean_var_186; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if (value != ((void*)0)) _g_boolean_var_187 = 1; else _g_boolean_var_187
= 0; _g_boolean_var_187; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if (info != ((void*)0)) _g_boolean_var_188 = 1; else _g_boolean_var_188
= 0; _g_boolean_var_188; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if (value != ((void*)0)) _g_boolean_var_189 = 1; else _g_boolean_var_189
= 0; _g_boolean_var_189; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if (info != ((void*)0)) _g_boolean_var_190 = 1; else _g_boolean_var_190
= 0; _g_boolean_var_190; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if (value != ((void*)0)) _g_boolean_var_191 = 1; else _g_boolean_var_191
= 0; _g_boolean_var_191; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if (info != ((void*)0)) _g_boolean_var_192 = 1; else _g_boolean_var_192
= 0; _g_boolean_var_192; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if (value != ((void*)0)) _g_boolean_var_193 = 1; else _g_boolean_var_193
= 0; _g_boolean_var_193; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if (info != ((void*)0)) _g_boolean_var_194 = 1; else _g_boolean_var_194
= 0; _g_boolean_var_194; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if (value != ((void*)0)) _g_boolean_var_195 = 1; else _g_boolean_var_195
= 0; _g_boolean_var_195; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if (info != ((void*)0)) _g_boolean_var_196 = 1; else _g_boolean_var_196
= 0; _g_boolean_var_196; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if (value != ((void*)0)) _g_boolean_var_197 = 1; else _g_boolean_var_197
= 0; _g_boolean_var_197; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if (info != ((void*)0)) _g_boolean_var_198 = 1; else _g_boolean_var_198
= 0; _g_boolean_var_198; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if (value != ((void*)0)) _g_boolean_var_199 = 1; else _g_boolean_var_199
= 0; _g_boolean_var_199; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if (info != ((void*)0)) _g_boolean_var_200 = 1; else _g_boolean_var_200
= 0; _g_boolean_var_200; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if (value != ((void*)0)) _g_boolean_var_201 = 1; else _g_boolean_var_201
= 0; _g_boolean_var_201; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (info != ((void*)0)) _g_boolean_var_202 = 1; else _g_boolean_var_202
= 0; _g_boolean_var_202; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if (value != ((void*)0)) _g_boolean_var_203 = 1; else _g_boolean_var_203
= 0; _g_boolean_var_203; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if (info != ((void*)0)) _g_boolean_var_204 = 1; else _g_boolean_var_204
= 0; _g_boolean_var_204; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if (speed != ((void*)0)) _g_boolean_var_205 = 1; else _g_boolean_var_205
= 0; _g_boolean_var_205; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (direction != ((void*)0)) _g_boolean_var_206 = 1; else _g_boolean_var_206
= 0; _g_boolean_var_206; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if (info != ((void*)0)) _g_boolean_var_207 = 1; else _g_boolean_var_207
= 0; _g_boolean_var_207; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if (value != ((void*)0)) _g_boolean_var_208 = 1; else _g_boolean_var_208
= 0; _g_boolean_var_208; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if (info != ((void*)0)) _g_boolean_var_209 = 1; else _g_boolean_var_209
= 0; _g_boolean_var_209; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if (value != ((void*)0)) _g_boolean_var_210 = 1; else _g_boolean_var_210
= 0; _g_boolean_var_210; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if (info != ((void*)0)) _g_boolean_var_211 = 1; else _g_boolean_var_211
= 0; _g_boolean_var_211; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if (phases != ((void*)0)) _g_boolean_var_212 = 1; else _g_boolean_var_212
= 0; _g_boolean_var_212; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_213 = 1; else _g_boolean_var_213
= 0; _g_boolean_var_213; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_214 = 1; else _g_boolean_var_214 = 0; _g_boolean_var_214
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_215 = 1; else _g_boolean_var_215
= 0; _g_boolean_var_215; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_216 = 1; else _g_boolean_var_216
= 0; _g_boolean_var_216; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-d766a0.html b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-d766a0.html new file mode 100644 index 00000000..cecb4e00 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-180813-5854-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (info != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (metar != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (info != ((void*)0)) _g_boolean_var_24 = 1; else _g_boolean_var_24
= 0; _g_boolean_var_24; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (info != ((void*)0)) _g_boolean_var_25 = 1; else _g_boolean_var_25
= 0; _g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/scanview.css b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/sorttable.js b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-09-01-180813-5854-1@e4cb5aac0a7c_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/1.html b/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/1.html new file mode 100644 index 00000000..95970ba7 --- /dev/null +++ b/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/index.html b/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/stats.html b/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/style.css b/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-09-01-180916-6520-cppcheck@e4cb5aac0a7c_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-09-01-181303-5846-1@58a183825058_master/index.html b/2023-09-01-181303-5846-1@58a183825058_master/index.html new file mode 100644 index 00000000..748af2a8 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/index.html @@ -0,0 +1,133 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@ef0a9fddd578
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 16.0.6 (Fedora 16.0.6-2.fc38) +
Date:Fri Sep 1 18:13:03 2023
+

Bug Summary

+ + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs11
Logic error
Dereference of null pointer1
Out-of-bound access2
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unix Stream API Error
Resource Leak1
Unused code
Dead assignment2
Dead initialization2
Unreachable code2
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentweather.c_weather_info_fill4951View Report
Unused codeDead assignmentweather-metar.cmetar_parse4541View Report
Unused codeDead initializationweather-sun.ccalc_sun21631View Report
Unused codeDead initializationweather-sun.ccalc_sun21621View Report
Logic errorDereference of null pointerweather-met.cmet_reprocess11127View Report
Logic errorOut-of-bound accessweather-met.cmet_reprocess11148View Report
Logic errorOut-of-bound accessweather-metar.cmetar_tok_vis1699View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'weather.cweather_info_get_update7191View Report
Unix Stream API ErrorResource Leaktest_metar.cmain738View Report
Unused codeUnreachable codeweather-metar.cmetar_tok_vis1771View Report
Unused codeUnreachable codeweather-sun.cweather_info_next_sun_event3351View Report
+ + diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-0d7031.html b/2023-09-01-181303-5846-1@58a183825058_master/report-0d7031.html new file mode 100644 index 00000000..80fd975a --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-0d7031.html @@ -0,0 +1,1000 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
22
Assuming 'buflen' is < 'len'
23
Taking true branch
43 {
44 if (buf
23.1
'buf' is null
)
24
Taking false branch
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
51 x += len; /* End mark */
52
53 while (*p && p
25.1
'p' is < 'x'
< x
) {
25
Assuming the condition is true
26
Loop condition is true. Entering loop body
41
Execution continues on line 53
42
Assuming the condition is true
43
Assuming 'p' is >= 'x'
44
Loop condition is false. Execution continues on line 111
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
27
Assuming the condition is false
28
Taking false branch
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count
28.1
'count' is <= 75
> 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
29
Assuming the condition is false
30
Taking false branch
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
31
Assuming the condition is true
32
Taking true branch
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
33
Assuming the condition is true
34
Taking true branch
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
37
Assuming the condition is true
38
Assuming the condition is false
39
Loop condition is false. Execution continues on line 104
103 p++;
104 if (*p)
40
Taking true branch
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
45
Out of bound memory access (access exceeds upper limit of memory block)
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n")g_strdup_inline ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (meto != ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (p != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (rp != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (info != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-1b914f.html b/2023-09-01-181303-5846-1@58a183825058_master/report-1b914f.html new file mode 100644 index 00000000..b1afea61 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-1b914f.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 163, column 13
Value stored to 'obsLon' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
Value stored to 'obsLon' during its initialization is never read
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_12
; if (info != ((void*)0)) _g_boolean_var_12 = 1; else _g_boolean_var_12
= 0; _g_boolean_var_12; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-20fe9d.html b/2023-09-01-181303-5846-1@58a183825058_master/report-20fe9d.html new file mode 100644 index 00000000..ba9b621d --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-20fe9d.html @@ -0,0 +1,944 @@ + + + +weather-met.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-met.c
Warning:line 111, column 8
Dereference of null pointer (loaded from variable 'o')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-met.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather-met.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-met.c - UK Met Office forecast source
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26
27#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
28#include "weather.h"
29#include "weather-priv.h"
30
31static char *
32met_reprocess (char *x, int len)
33{
34 char *p = x;
35 char *o;
36 int spacing = 0;
37 static gchar *buf;
22
'buf' initialized to a null pointer value
38 static gint buflen = 0;
39 gchar *lastspace = NULL((void*)0);
40 int count = 0;
41
42 if (buflen < len)
23
Assuming 'buflen' is >= 'len'
24
Taking false branch
43 {
44 if (buf)
45 g_free (buf);
46 buf = g_malloc (len + 1);
47 buflen = len;
48 }
49
50 o = buf;
25
Null pointer value stored to 'o'
51 x += len; /* End mark */
52
53 while (*p && p < x) {
26
Assuming the condition is false
54 if (g_ascii_isspace (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0)) {
55 if (!spacing) {
56 spacing = 1;
57 lastspace = o;
58 count++;
59 *o++ = ' ';
60 }
61 p++;
62 continue;
63 }
64 spacing = 0;
65 if (count > 75 && lastspace) {
66 count = o - lastspace - 1;
67 *lastspace = '\n';
68 lastspace = NULL((void*)0);
69 }
70
71 if (*p == '&') {
72 if (g_ascii_strncasecmp (p, "&amp;", 5) == 0) {
73 *o++ = '&';
74 count++;
75 p += 5;
76 continue;
77 }
78 if (g_ascii_strncasecmp (p, "&lt;", 4) == 0) {
79 *o++ = '<';
80 count++;
81 p += 4;
82 continue;
83 }
84 if (g_ascii_strncasecmp (p, "&gt;", 4) == 0) {
85 *o++ = '>';
86 count++;
87 p += 4;
88 continue;
89 }
90 }
91 if (*p == '<') {
92 if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) {
93 *o++ = '\n';
94 count = 0;
95 }
96 if (g_ascii_strncasecmp (p, "<B>", 3) == 0) {
97 *o++ = '\n';
98 *o++ = '\n';
99 count = 0;
100 }
101 p++;
102 while (*p && *p != '>')
103 p++;
104 if (*p)
105 p++;
106 continue;
107 }
108 *o++ = *p++;
109 count++;
110 }
111 *o = 0;
27
Dereference of null pointer (loaded from variable 'o')
112 return buf;
113}
114
115/*
116 * Parse the metoffice forecast info.
117 * For mate 3.0 we want to just embed an HTML matecomponent component and
118 * be done with this ;)
119 */
120
121static gchar *
122met_parse (const gchar *meto)
123{
124 gchar *p;
125 gchar *rp;
126 gchar *r = g_strdup ("Met Office Forecast\n")g_strdup_inline ("Met Office Forecast\n");
127 gchar *t;
128
129 g_return_val_if_fail (meto != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_14
; if (meto != ((void*)0)) _g_boolean_var_14 = 1; else _g_boolean_var_14
= 0; _g_boolean_var_14; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "meto != NULL");
return (r); } } while (0)
;
9
Assuming 'meto' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
130
131 p = strstr (meto, "Summary: </b>");
132 g_return_val_if_fail (p != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_15
; if (p != ((void*)0)) _g_boolean_var_15 = 1; else _g_boolean_var_15
= 0; _g_boolean_var_15; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "p != NULL"); return
(r); } } while (0)
;
13
Assuming 'p' is not equal to null
14
Taking true branch
15
Taking true branch
16
Loop condition is false. Exiting loop
133
134 rp = strstr (p, "Text issued at:");
135 g_return_val_if_fail (rp != NULL, r)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (rp != ((void*)0)) _g_boolean_var_16 = 1; else _g_boolean_var_16
= 0; _g_boolean_var_16; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "rp != NULL"); return
(r); } } while (0)
;
17
Assuming 'rp' is not equal to null
18
Taking true branch
19
Taking true branch
20
Loop condition is false. Exiting loop
136
137 p += 13;
138 /* p to rp is the text block we want but in HTML malformat */
139 t = g_strconcat (r, met_reprocess (p, rp - p), NULL((void*)0));
21
Calling 'met_reprocess'
140 g_free (r);
141
142 return t;
143}
144
145static void
146met_finish (SoupSession *session, SoupMessage *msg, gpointer data)
147{
148 WeatherInfo *info = (WeatherInfo *)data;
149
150 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (info != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
1
Assuming 'info' is not equal to null
2
Taking true branch
3
Taking true branch
151
152 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
4
Loop condition is false. Exiting loop
5
Assuming field 'status_code' is >= 200
6
Assuming field 'status_code' is < 300
7
Taking false branch
153 g_warning ("Failed to get Met Office forecast data: %d %s.\n",
154 msg->status_code, msg->reason_phrase);
155 request_done (info, FALSE(0));
156 return;
157 }
158
159 info->forecast = met_parse (msg->response_body->data);
8
Calling 'met_parse'
160 request_done (info, TRUE(!(0)));
161}
162
163void
164metoffice_start_open (WeatherInfo *info)
165{
166 gchar *url;
167 SoupMessage *msg;
168 WeatherLocation *loc;
169
170 loc = info->location;
171 url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1);
172
173 msg = soup_message_new ("GET", url);
174 soup_session_queue_message (info->session, msg, met_finish, info);
175 g_free (url);
176
177 info->requests_pending++;
178}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-339c98.html b/2023-09-01-181303-5846-1@58a183825058_master/report-339c98.html new file mode 100644 index 00000000..0e484ea7 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-339c98.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 162, column 13
Value stored to 'obsLat' during its initialization is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
Value stored to 'obsLat' during its initialization is never read
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_11
; if (info != ((void*)0)) _g_boolean_var_11 = 1; else _g_boolean_var_11
= 0; _g_boolean_var_11; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-3d7553.html b/2023-09-01-181303-5846-1@58a183825058_master/report-3d7553.html new file mode 100644 index 00000000..e3fa21d7 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-3d7553.html @@ -0,0 +1,775 @@ + + + +test_metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test_metar.c
Warning:line 73, column 12
Opened file is never closed; potential resource leak
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c test_metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3 * Simple program to reproduce METAR parsing results from command line
4 */
5
6#include <glib.h>
7#include <string.h>
8#include <stdio.h>
9#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
10#include "weather-priv.h"
11
12#ifndef BUFLEN4096
13#define BUFLEN4096 4096
14#endif /* BUFLEN */
15
16int
17main (int argc, char **argv)
18{
19 FILE* stream = stdinstdin;
20 gchar* filename = NULL((void*)0);
21 GOptionEntry entries[] = {
22 { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename,
23 "file constaining metar observations", NULL((void*)0) },
24 { NULL((void*)0), 0, 0, G_OPTION_ARG_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0) }
25 };
26 GOptionContext* context;
27 GError* error = NULL((void*)0);
28 char buf[BUFLEN4096];
29 int len;
30 WeatherInfo info;
31
32 context = g_option_context_new ("- test libmateweather metar parser");
33 g_option_context_add_main_entries (context, entries, NULL((void*)0));
34 g_option_context_parse (context, &argc, &argv, &error);
35
36 if (error) {
1
Assuming 'error' is null
2
Taking false branch
37 perror (error->message);
38 return error->code;
39 }
40 if (filename) {
3
Assuming 'filename' is non-null
4
Taking true branch
41 stream = fopen (filename, "r");
42 if (!stream) {
5
Assuming 'stream' is non-null
6
Taking false branch
43 perror ("fopen");
44 return -1;
45 }
46 } else {
47 fprintf (stderrstderr, "Enter a METAR string...\n");
48 }
49
50 while (fgets (buf, sizeof (buf), stream)) {
7
Loop condition is false. Execution continues on line 73
51 len = strlen (buf);
52 if (buf[len - 1] == '\n') {
53 buf[--len] = '\0';
54 }
55 printf ("\n%s\n", buf);
56
57 memset (&info, 0, sizeof (info));
58 info.valid = 1;
59 metar_parse (buf, &info);
60 weather_info_to_metric (&info);
61 printf ("Returned info:\n");
62 printf (" update: %s", ctime (&info.update));
63 printf (" sky: %s\n", weather_info_get_sky (&info));
64 printf (" cond: %s\n", weather_info_get_conditions (&info));
65 printf (" temp: %s\n", weather_info_get_temp (&info));
66 printf (" dewp: %s\n", weather_info_get_dew (&info));
67 printf (" wind: %s\n", weather_info_get_wind (&info));
68 printf (" pressure: %s\n", weather_info_get_pressure (&info));
69 printf (" vis: %s\n", weather_info_get_visibility (&info));
70
71 // TODO: retrieve location's lat/lon to display sunrise/set times
72 }
73 return 0;
8
Opened file is never closed; potential resource leak
74}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-54e1e1.html b/2023-09-01-181303-5846-1@58a183825058_master/report-54e1e1.html new file mode 100644 index 00000000..6e62ced5 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-54e1e1.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 177, column 28
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
This statement is never executed
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (info != ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (metar != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (info != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (info != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-688a74.html b/2023-09-01-181303-5846-1@58a183825058_master/report-688a74.html new file mode 100644 index 00000000..ce115dd9 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-688a74.html @@ -0,0 +1,1029 @@ + + + +weather-sun.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-sun.c
Warning:line 335, column 12
This statement is never executed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-sun.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather-sun.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-sun.c - Astronomy calculations for mateweather
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Formulas from:
21 * "Practical Astronomy With Your Calculator" (3e), Peter Duffett-Smith
22 * Cambridge University Press 1988
23 * Unless otherwise noted, comments referencing "steps" are related to
24 * the algorithm presented in section 49 of above
25 */
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30
31#include <math.h>
32#include <time.h>
33#include <glib.h>
34
35#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
36#include "weather-priv.h"
37
38#define ECCENTRICITY(d)(0.01671123 - (d)/36525.*0.00004392) (0.01671123 - (d)/36525.*0.00004392)
39
40/*
41 * Ecliptic longitude of the sun at specified time (UT)
42 * The algoithm is described in section 47 of Duffett-Smith
43 * Return value is in radians
44 */
45gdouble
46sunEclipLongitude(time_t t)
47{
48 gdouble ndays, meanAnom, eccenAnom, delta, e, longitude;
49
50 /*
51 * Start with an estimate based on a fixed daily rate
52 */
53 ndays = EPOCH_TO_J2000(t)((gdouble)(t)-946727935.816) / 86400.;
54 meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays)((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
55 - PERIGEE_LONGITUDE(ndays))((fmod (((280.46457166 + (ndays)/36525.*35999.37244981) - (282.93768193
+ (ndays)/36525.*0.32327364)),360.) / 180.) * 3.14159265358979323846
)
;
56
57 /*
58 * Approximate solution of Kepler's equation:
59 * Find E which satisfies E - e sin(E) = M (mean anomaly)
60 */
61 eccenAnom = meanAnom;
62 e = ECCENTRICITY(ndays)(0.01671123 - (ndays)/36525.*0.00004392);
63
64 while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom))
65 {
66 eccenAnom -= delta / (1.- e * cos(eccenAnom));
67 }
68
69 /*
70 * Earth's longitude on the ecliptic
71 */
72 longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays))((fmod (((282.93768193 + (ndays)/36525.*0.32327364)),360.) / 180.
) * 3.14159265358979323846)
73 + 2. * atan (sqrt ((1.+e)/(1.-e))
74 * tan (eccenAnom / 2.)),
75 2. * M_PI3.14159265358979323846);
76 if (longitude < 0.) {
77 longitude += 2 * M_PI3.14159265358979323846;
78 }
79 return longitude;
80}
81
82static gdouble
83ecliptic_obliquity (gdouble time)
84{
85 gdouble jc = EPOCH_TO_J2000 (time)((gdouble)(time)-946727935.816) / (36525. * 86400.);
86 gdouble eclip_secs = (84381.448
87 - (46.84024 * jc)
88 - (59.e-5 * jc * jc)
89 + (1.813e-3 * jc * jc * jc));
90 return DEGREES_TO_RADIANS(eclip_secs / 3600.)((fmod ((eclip_secs / 3600.),360.) / 180.) * 3.14159265358979323846
)
;
91}
92
93/*
94 * Convert ecliptic longitude and latitude (radians) to equitorial
95 * coordinates, expressed as right ascension (hours) and
96 * declination (radians)
97 */
98void
99ecl2equ (gdouble time,
100 gdouble eclipLon, gdouble eclipLat,
101 gdouble *ra, gdouble *decl)
102{
103 gdouble mEclipObliq = ecliptic_obliquity(time);
104
105 if (ra) {
106 *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq)((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
107 - tan (eclipLat) * sin(mEclipObliq)),((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
108 cos (eclipLon)))((atan2 ((sin (eclipLon) * cos (mEclipObliq) - tan (eclipLat)
* sin(mEclipObliq)), cos (eclipLon))) * 12. / 3.14159265358979323846
)
;
109 if (*ra < 0.)
110 *ra += 24.;
111 }
112 if (decl) {
113 *decl = asin (( sin (eclipLat) * cos (mEclipObliq))
114 + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon));
115 }
116}
117
118/*
119 * Calculate rising and setting times for an object
120 * based on it equitorial coordinates (section 33 & 15)
121 * Returned "rise" and "set" values are sideral times in hours
122 */
123static void
124gstObsv (gdouble ra, gdouble decl,
125 gdouble obsLat, gdouble obsLon,
126 gdouble *rise, gdouble *set)
127{
128 double a = acos (-tan (obsLat) * tan (decl));
129 double b;
130
131 if (isnan (a)__builtin_isnan (a) != 0) {
132 *set = *rise = a;
133 return;
134 }
135 a = RADIANS_TO_HOURS (a)((a) * 12. / 3.14159265358979323846);
136 b = 24. - a + ra;
137 a += ra;
138 a -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
139 b -= RADIANS_TO_HOURS (obsLon)((obsLon) * 12. / 3.14159265358979323846);
140 if ((a = fmod (a, 24.)) < 0)
141 a += 24.;
142 if ((b = fmod (b, 24.)) < 0)
143 b += 24.;
144
145 *set = a;
146 *rise = b;
147}
148
149static gdouble
150t0 (time_t date)
151{
152 gdouble t = ((gdouble)(EPOCH_TO_J2000 (date)((gdouble)(date)-946727935.816) / 86400)) / 36525.0;
153 gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.);
154 if (t0 < 0.)
155 t0 += 24.;
156 return t0;
157}
158
159static gboolean
160calc_sun2 (WeatherInfo *info, time_t t)
161{
162 gdouble obsLat = info->location->latitude;
163 gdouble obsLon = info->location->longitude;
164 time_t gm_midn;
165 time_t lcl_midn;
166 gdouble gm_hoff, lambda;
167 gdouble ra1, ra2;
168 gdouble decl1, decl2;
169 gdouble decl_midn, decl_noon;
170 gdouble rise1, rise2;
171 gdouble set1, set2;
172 gdouble tt, t00;
173 gdouble x, u, dt;
174
175 /* Approximate preceding local midnight at observer's longitude */
176 obsLat = info->location->latitude;
177 obsLon = info->location->longitude;
178 gm_midn = t - (t % 86400);
179 gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon)((obsLon) * 180. / 3.14159265358979323846) + 7.5) / 15.);
180 lcl_midn = gm_midn - 3600. * gm_hoff;
181 if (t - lcl_midn >= 86400)
182 lcl_midn += 86400;
183 else if (lcl_midn > t)
184 lcl_midn -= 86400;
185
186 lambda = sunEclipLongitude (lcl_midn);
187
188 /*
189 * Calculate equitorial coordinates of sun at previous
190 * and next local midnights
191 */
192 ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1);
193 ecl2equ (lcl_midn + 86400.,
194 lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION)((fmod (((360./365.242191)),360.) / 180.) * 3.14159265358979323846
)
, 0.,
195 &ra2, &decl2);
196
197 /*
198 * If the observer is within the Arctic or Antarctic Circles then
199 * the sun may be above or below the horizon for the full day.
200 */
201 decl_midn = MIN(decl1,decl2)(((decl1) < (decl2)) ? (decl1) : (decl2));
202 decl_noon = (decl1+decl2)/2.;
203 info->midnightSun =
204 (obsLat > (M_PI3.14159265358979323846/2.-decl_midn)) || (obsLat < (-M_PI3.14159265358979323846/2.-decl_midn));
205 info->polarNight =
206 (obsLat > (M_PI3.14159265358979323846/2.+decl_noon)) || (obsLat < (-M_PI3.14159265358979323846/2.+decl_noon));
207 if (info->midnightSun || info->polarNight) {
208 info->sunriseValid = info->sunsetValid = FALSE(0);
209 return FALSE(0);
210 }
211
212 /*
213 * Convert to rise and set times based positions for the preceding
214 * and following local midnights.
215 */
216 gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise1, &set1);
217 gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI3.14159265358979323846 / 12.), &rise2, &set2);
218
219 /* TODO: include calculations for regions near the poles. */
220 if (isnan(rise1)__builtin_isnan (rise1) || isnan(rise2)__builtin_isnan (rise2)) {
221 info->sunriseValid = info->sunsetValid = FALSE(0);
222 return FALSE(0);
223 }
224
225 if (rise2 < rise1) {
226 rise2 += 24.;
227 }
228 if (set2 < set1) {
229 set2 += 24.;
230 }
231
232 tt = t0(lcl_midn);
233 t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)((obsLon) * 12. / 3.14159265358979323846)) * 1.002737909;
234
235 if (t00 < 0.)
236 t00 += 24.;
237
238 if (rise1 < t00) {
239 rise1 += 24.;
240 rise2 += 24.;
241 }
242 if (set1 < t00) {
243 set1 += 24.;
244 set2 += 24.;
245 }
246
247 /*
248 * Interpolate between the two to get a rise and set time
249 * based on the sun's position at local noon (step 8)
250 */
251 rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2);
252 set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2);
253
254 /*
255 * Calculate an adjustment value to account for parallax,
256 * refraction and the Sun's finite diameter (steps 9,10)
257 */
258 decl2 = (decl1 + decl2) / 2.;
259 x = DEGREES_TO_RADIANS(0.830725)((fmod ((0.830725),360.) / 180.) * 3.14159265358979323846);
260 u = acos ( sin(obsLat) / cos(decl2) );
261 dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) )((asin ( sin(x) / sin(u) ) / cos(decl2)) * 12. / 3.14159265358979323846
)
;
262
263 /*
264 * Subtract the correction value from sunrise and add to sunset,
265 * then (step 11) convert sideral times to UT
266 */
267 rise1 = (rise1 - dt - tt) * 0.9972695661;
268 if (rise1 < 0.)
269 rise1 += 24;
270 else if (rise1 >= 24.)
271 rise1 -= 24.;
272 info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.));
273 info->sunrise = (rise1 * 3600.) + lcl_midn;
274
275 set1 = (set1 + dt - tt) * 0.9972695661;
276 if (set1 < 0.)
277 set1 += 24;
278 else if (set1 >= 24.)
279 set1 -= 24.;
280 info->sunsetValid = ((set1 >= 0.) && (set1 < 24.));
281 info->sunset = (set1 * 3600.) + lcl_midn;
282
283 return (info->sunriseValid || info->sunsetValid);
284}
285
286/**
287 * calc_sun_time:
288 * @info: #WeatherInfo structure containing the observer's latitude
289 * and longitude in radians, fills in the sunrise and sunset times.
290 * @t: time_t
291 *
292 * Returns: gboolean indicating if the results are valid.
293 */
294gboolean
295calc_sun_time (WeatherInfo *info, time_t t)
296{
297 return info->location->latlon_valid && calc_sun2 (info, t);
298}
299
300/**
301 * calc_sun:
302 * @info: #WeatherInfo structure containing the observer's latitude
303 * and longitude in radians, fills in the sunrise and sunset times.
304 *
305 * Returns: gboolean indicating if the results are valid.
306 */
307gboolean
308calc_sun (WeatherInfo *info)
309{
310 return calc_sun_time(info, time(NULL((void*)0)));
311}
312
313/**
314 * weather_info_next_sun_event:
315 * @info: #WeatherInfo structure
316 *
317 * Returns: the interval, in seconds, until the next "sun event":
318 * - local midnight, when rise and set times are recomputed
319 * - next sunrise, when icon changes to daytime version
320 * - next sunset, when icon changes to nighttime version
321 */
322gint
323weather_info_next_sun_event (WeatherInfo *info)
324{
325 time_t now = time (NULL((void*)0));
326 struct tm ltm;
327 time_t nxtEvent;
328
329 g_return_val_if_fail (info != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_13
; if (info != ((void*)0)) _g_boolean_var_13 = 1; else _g_boolean_var_13
= 0; _g_boolean_var_13; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (-1); } } while (0)
;
330
331 if (!calc_sun (info))
332 return -1;
333
334 /* Determine when the next local midnight occurs */
335 (void) localtime_r (&now, &ltm);
This statement is never executed
336 ltm.tm_sec = 0;
337 ltm.tm_min = 0;
338 ltm.tm_hour = 0;
339 ltm.tm_mday++;
340 nxtEvent = mktime (&ltm);
341
342 if (info->sunsetValid &&
343 (info->sunset > now) && (info->sunset < nxtEvent))
344 nxtEvent = info->sunset;
345 if (info->sunriseValid &&
346 (info->sunrise > now) && (info->sunrise < nxtEvent))
347 nxtEvent = info->sunrise;
348 return (gint)(nxtEvent - now);
349}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-72c2f8.html b/2023-09-01-181303-5846-1@58a183825058_master/report-72c2f8.html new file mode 100644 index 00000000..d67cd283 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-72c2f8.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 495, column 9
Value stored to 'location' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_79; if
((__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_79 = 1; else _g_boolean_var_79 = 0; _g_boolean_var_79
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name)g_strdup_inline (name);
135 location->code = g_strdup (code)g_strdup_inline (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone)g_strdup_inline (zone);
139 } else {
140 location->zone = g_strdup ("------")g_strdup_inline ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar)g_strdup_inline (radar);
145 } else {
146 location->radar = g_strdup ("---")g_strdup_inline ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates)g_strdup_inline (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---")g_strdup_inline ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code)g_strdup_inline (country_code);
182 location->tz_hint = g_strdup (tz_hint)g_strdup_inline (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_80
; if (location != ((void*)0)) _g_boolean_var_80 = 1; else _g_boolean_var_80
= 0; _g_boolean_var_80; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_81 = 1; else _g_boolean_var_81 = 0; _g_boolean_var_81
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_81 = 1; else _g_boolean_var_81 = 0; _g_boolean_var_81
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_82
; if (prefs != ((void*)0)) _g_boolean_var_82 = 1; else _g_boolean_var_82
= 0; _g_boolean_var_82; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
Value stored to 'location' is never read
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url)g_strdup_inline (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_83
; if (info != ((void*)0)) _g_boolean_var_83 = 1; else _g_boolean_var_83
= 0; _g_boolean_var_83; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_84
; if (info != ((void*)0)) _g_boolean_var_84 = 1; else _g_boolean_var_84
= 0; _g_boolean_var_84; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast)g_strdup_inline (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url)g_strdup_inline (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_85
; if (info != ((void*)0)) _g_boolean_var_85 = 1; else _g_boolean_var_85
= 0; _g_boolean_var_85; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_86
; if (info != ((void*)0)) _g_boolean_var_86 = 1; else _g_boolean_var_86
= 0; _g_boolean_var_86; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_87
; if (info != ((void*)0)) _g_boolean_var_87 = 1; else _g_boolean_var_87
= 0; _g_boolean_var_87; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_88
; if (info != ((void*)0)) _g_boolean_var_88 = 1; else _g_boolean_var_88
= 0; _g_boolean_var_88; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_89
; if (info != ((void*)0)) _g_boolean_var_89 = 1; else _g_boolean_var_89
= 0; _g_boolean_var_89; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_90
; if (info != ((void*)0)) _g_boolean_var_90 = 1; else _g_boolean_var_90
= 0; _g_boolean_var_90; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_91
; if (info->location != ((void*)0)) _g_boolean_var_91 = 1;
else _g_boolean_var_91 = 0; _g_boolean_var_91; }), 1))) { } else
{ g_return_if_fail_warning ("MateWeather", ((const char*) (__func__
)), "info->location != NULL"); return (((void*)0)); } } while
(0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_92
; if (info != ((void*)0)) _g_boolean_var_92 = 1; else _g_boolean_var_92
= 0; _g_boolean_var_92; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
; if (info != ((void*)0)) _g_boolean_var_93 = 1; else _g_boolean_var_93
= 0; _g_boolean_var_93; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_94
; if (info != ((void*)0)) _g_boolean_var_94 = 1; else _g_boolean_var_94
= 0; _g_boolean_var_94; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_95
; if (info != ((void*)0)) _g_boolean_var_95 = 1; else _g_boolean_var_95
= 0; _g_boolean_var_95; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_96
; if (info != ((void*)0)) _g_boolean_var_96 = 1; else _g_boolean_var_96
= 0; _g_boolean_var_96; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_97
; if (info != ((void*)0)) _g_boolean_var_97 = 1; else _g_boolean_var_97
= 0; _g_boolean_var_97; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_98
; if (info != ((void*)0)) _g_boolean_var_98 = 1; else _g_boolean_var_98
= 0; _g_boolean_var_98; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_99
; if (info != ((void*)0)) _g_boolean_var_99 = 1; else _g_boolean_var_99
= 0; _g_boolean_var_99; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
; if (info != ((void*)0)) _g_boolean_var_100 = 1; else _g_boolean_var_100
= 0; _g_boolean_var_100; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (info != ((void*)0)) _g_boolean_var_101 = 1; else _g_boolean_var_101
= 0; _g_boolean_var_101; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_102
; if (info != ((void*)0)) _g_boolean_var_102 = 1; else _g_boolean_var_102
= 0; _g_boolean_var_102; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_103
; if (info != ((void*)0)) _g_boolean_var_103 = 1; else _g_boolean_var_103
= 0; _g_boolean_var_103; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if (info && info->location) _g_boolean_var_104 =
1; else _g_boolean_var_104 = 0; _g_boolean_var_104; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if (info && info->location) _g_boolean_var_105 =
1; else _g_boolean_var_105 = 0; _g_boolean_var_105; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if (info != ((void*)0)) _g_boolean_var_106 = 1; else _g_boolean_var_106
= 0; _g_boolean_var_106; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if (info != ((void*)0)) _g_boolean_var_107 = 1; else _g_boolean_var_107
= 0; _g_boolean_var_107; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if (info != ((void*)0)) _g_boolean_var_108 = 1; else _g_boolean_var_108
= 0; _g_boolean_var_108; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if (info != ((void*)0)) _g_boolean_var_109 = 1; else _g_boolean_var_109
= 0; _g_boolean_var_109; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if (info != ((void*)0)) _g_boolean_var_110 = 1; else _g_boolean_var_110
= 0; _g_boolean_var_110; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed"))g_strdup_inline ((mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if (info != ((void*)0)) _g_boolean_var_111 = 1; else _g_boolean_var_111
= 0; _g_boolean_var_111; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if (info != ((void*)0)) _g_boolean_var_112 = 1; else _g_boolean_var_112
= 0; _g_boolean_var_112; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if (sky != ((void*)0)) _g_boolean_var_113 = 1; else _g_boolean_var_113
= 0; _g_boolean_var_113; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if (info != ((void*)0)) _g_boolean_var_114 = 1; else _g_boolean_var_114
= 0; _g_boolean_var_114; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if (phenomenon != ((void*)0)) _g_boolean_var_115 = 1; else _g_boolean_var_115
= 0; _g_boolean_var_115; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if (qualifier != ((void*)0)) _g_boolean_var_116 = 1; else _g_boolean_var_116
= 0; _g_boolean_var_116; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if (info != ((void*)0)) _g_boolean_var_117 = 1; else _g_boolean_var_117
= 0; _g_boolean_var_117; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if (value != ((void*)0)) _g_boolean_var_118 = 1; else _g_boolean_var_118
= 0; _g_boolean_var_118; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if (info != ((void*)0)) _g_boolean_var_119 = 1; else _g_boolean_var_119
= 0; _g_boolean_var_119; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (value != ((void*)0)) _g_boolean_var_120 = 1; else _g_boolean_var_120
= 0; _g_boolean_var_120; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if (info != ((void*)0)) _g_boolean_var_121 = 1; else _g_boolean_var_121
= 0; _g_boolean_var_121; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if (value != ((void*)0)) _g_boolean_var_122 = 1; else _g_boolean_var_122
= 0; _g_boolean_var_122; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if (info != ((void*)0)) _g_boolean_var_123 = 1; else _g_boolean_var_123
= 0; _g_boolean_var_123; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if (value != ((void*)0)) _g_boolean_var_124 = 1; else _g_boolean_var_124
= 0; _g_boolean_var_124; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if (info != ((void*)0)) _g_boolean_var_125 = 1; else _g_boolean_var_125
= 0; _g_boolean_var_125; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if (value != ((void*)0)) _g_boolean_var_126 = 1; else _g_boolean_var_126
= 0; _g_boolean_var_126; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if (info != ((void*)0)) _g_boolean_var_127 = 1; else _g_boolean_var_127
= 0; _g_boolean_var_127; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if (value != ((void*)0)) _g_boolean_var_128 = 1; else _g_boolean_var_128
= 0; _g_boolean_var_128; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if (info != ((void*)0)) _g_boolean_var_129 = 1; else _g_boolean_var_129
= 0; _g_boolean_var_129; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if (value != ((void*)0)) _g_boolean_var_130 = 1; else _g_boolean_var_130
= 0; _g_boolean_var_130; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if (info != ((void*)0)) _g_boolean_var_131 = 1; else _g_boolean_var_131
= 0; _g_boolean_var_131; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_132
; if (value != ((void*)0)) _g_boolean_var_132 = 1; else _g_boolean_var_132
= 0; _g_boolean_var_132; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if (info != ((void*)0)) _g_boolean_var_133 = 1; else _g_boolean_var_133
= 0; _g_boolean_var_133; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (value != ((void*)0)) _g_boolean_var_134 = 1; else _g_boolean_var_134
= 0; _g_boolean_var_134; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if (info != ((void*)0)) _g_boolean_var_135 = 1; else _g_boolean_var_135
= 0; _g_boolean_var_135; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if (speed != ((void*)0)) _g_boolean_var_136 = 1; else _g_boolean_var_136
= 0; _g_boolean_var_136; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if (direction != ((void*)0)) _g_boolean_var_137 = 1; else _g_boolean_var_137
= 0; _g_boolean_var_137; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if (info != ((void*)0)) _g_boolean_var_138 = 1; else _g_boolean_var_138
= 0; _g_boolean_var_138; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if (value != ((void*)0)) _g_boolean_var_139 = 1; else _g_boolean_var_139
= 0; _g_boolean_var_139; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if (info != ((void*)0)) _g_boolean_var_140 = 1; else _g_boolean_var_140
= 0; _g_boolean_var_140; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (value != ((void*)0)) _g_boolean_var_141 = 1; else _g_boolean_var_141
= 0; _g_boolean_var_141; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if (info != ((void*)0)) _g_boolean_var_142 = 1; else _g_boolean_var_142
= 0; _g_boolean_var_142; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if (phases != ((void*)0)) _g_boolean_var_143 = 1; else _g_boolean_var_143
= 0; _g_boolean_var_143; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_144 = 1; else _g_boolean_var_144
= 0; _g_boolean_var_144; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_145 = 1; else _g_boolean_var_145 = 0; _g_boolean_var_145
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_146 = 1; else _g_boolean_var_146
= 0; _g_boolean_var_146; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_147 = 1; else _g_boolean_var_147
= 0; _g_boolean_var_147; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-9ba4eb.html b/2023-09-01-181303-5846-1@58a183825058_master/report-9ba4eb.html new file mode 100644 index 00000000..02622cfd --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-9ba4eb.html @@ -0,0 +1,1266 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 169, column 24
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
1
Assuming the condition is false
2
Taking false branch
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
3
Assuming the condition is true
4
Taking true branch
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
5
Assuming 'pfrac' is non-null
6
Taking true branch
166 if (*tokp == 'M') {
7
Assuming the condition is false
8
Taking false branch
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
9
Out of bound memory access (access exceeds upper limit of memory block)
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_14
; if (info != ((void*)0)) _g_boolean_var_14 = 1; else _g_boolean_var_14
= 0; _g_boolean_var_14; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_15
; if (metar != ((void*)0)) _g_boolean_var_15 = 1; else _g_boolean_var_15
= 0; _g_boolean_var_15; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (info != ((void*)0)) _g_boolean_var_16 = 1; else _g_boolean_var_16
= 0; _g_boolean_var_16; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (info != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-9e62c0.html b/2023-09-01-181303-5846-1@58a183825058_master/report-9e62c0.html new file mode 100644 index 00000000..11ab9bc1 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-9e62c0.html @@ -0,0 +1,2352 @@ + + + +weather.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather.c
Warning:line 719, column 2
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29#include <fenv.h>
30
31#ifdef HAVE_VALUES_H
32#include <values.h>
33#endif
34
35#include <time.h>
36#include <unistd.h>
37
38#include <gdk-pixbuf/gdk-pixbuf.h>
39
40#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
41#include "weather.h"
42#include "weather-priv.h"
43
44#define MOON_PHASES36 36
45
46/**
47 * SECTION:weather
48 * @Title: weather
49 */
50
51static void _weather_internal_check (void);
52
53static inline void
54mateweather_gettext_init (void)
55{
56 static gsize mateweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))(__builtin_expect (__extension__ ({ int _g_boolean_var_148; if
((__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&mateweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
mateweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&mateweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&mateweather_gettext_initialized)) gapg_temp_atomic
= (&mateweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&mateweather_gettext_initialized)); }
))) _g_boolean_var_148 = 1; else _g_boolean_var_148 = 0; _g_boolean_var_148
; }), 0))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libmateweather", MATELOCALEDIR"/usr/local/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libmateweather", "UTF-8");
62#endif
63 g_once_init_leave (&mateweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&mateweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&mateweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&mateweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68mateweather_gettext (const char *str)
69{
70 mateweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE, str)dcgettext ("libmateweather", str, 5);
72}
73
74const char *
75mateweather_dpgettext (const char *context,
76 const char *str)
77{
78 mateweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libmateweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)(WeatherLocation *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (WeatherLocation); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name)g_strdup_inline (name);
135 location->code = g_strdup (code)g_strdup_inline (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone)g_strdup_inline (zone);
139 } else {
140 location->zone = g_strdup ("------")g_strdup_inline ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar)g_strdup_inline (radar);
145 } else {
146 location->radar = g_strdup ("---")g_strdup_inline ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates)g_strdup_inline (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---")g_strdup_inline ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code)g_strdup_inline (country_code);
182 location->tz_hint = g_strdup (tz_hint)g_strdup_inline (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if (location != ((void*)0)) _g_boolean_var_149 = 1; else _g_boolean_var_149
= 0; _g_boolean_var_149; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(mateweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(mateweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(mateweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(mateweather_gettext (sky_str[(int)sky]));
267}
268
269/*
270 * Even though tedious, I switched to a 2D array for weather condition
271 * strings, in order to facilitate internationalization, esp. for languages
272 * with genders.
273 */
274
275/*
276 * Almost all reportable combinations listed in
277 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
278 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
279 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
280 * Combinations that are not possible are filled in with "??".
281 * Some other exceptions not handled yet, such as "SN BLSN" which has
282 * special meaning.
283 */
284
285/*
286 * Note, magic numbers, when you change the size here, make sure to change
287 * the below function so that new values are recognized
288 */
289/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
290/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
291static const gchar *conditions_str[24][13] = {
292/* Translators: If you want to know what "blowing" "shallow" "partial"
293 * etc means, you can go to http://www.weather.com/glossary/ and
294 * http://www.crh.noaa.gov/arx/wx.tbl.php */
295 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
296 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
297 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
298 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
299 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
300 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
302 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
303 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
304 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
305 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
307 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
308 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
310 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
311 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
312 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
313 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
314 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
319};
320
321const gchar *
322weather_conditions_string (WeatherConditions cond)
323{
324 const gchar *str;
325
326 if (!cond.significant) {
327 return "-";
328 } else {
329 if (cond.phenomenon > PHENOMENON_INVALID &&
330 cond.phenomenon < PHENOMENON_LAST &&
331 cond.qualifier > QUALIFIER_INVALID &&
332 cond.qualifier < QUALIFIER_LAST)
333 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(mateweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
334 else
335 str = _("Invalid")(mateweather_gettext ("Invalid"));
336 return (strlen (str) > 0) ? str : "-";
337 }
338}
339
340/* Locals turned global to facilitate asynchronous HTTP requests */
341
342gboolean
343requests_init (WeatherInfo *info)
344{
345 if (info->requests_pending)
346 return FALSE(0);
347
348 return TRUE(!(0));
349}
350
351void request_done (WeatherInfo *info, gboolean ok)
352{
353 if (ok) {
354 (void) calc_sun (info);
355 info->moonValid = info->valid && calc_moon (info);
356 }
357 if (!--info->requests_pending)
358 info->finish_cb (info, info->cb_data);
359}
360
361/* it's OK to pass in NULL */
362void
363free_forecast_list (WeatherInfo *info)
364{
365 GSList *p;
366
367 if (!info)
368 return;
369
370 for (p = info->forecast_list; p; p = p->next)
371 weather_info_free (p->data);
372
373 if (info->forecast_list) {
374 g_slist_free (info->forecast_list);
375 info->forecast_list = NULL((void*)0);
376 }
377}
378
379/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
380
381static inline gdouble
382calc_humidity (gdouble temp, gdouble dewp)
383{
384 gdouble esat, esurf;
385
386 if (temp > -500.0 && dewp > -500.0) {
387 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0));
388 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * (5.0/9.0));
389
390 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
391 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
392 } else {
393 esurf = -1.0;
394 esat = 1.0;
395 }
396 return ((esurf/esat) * 100.0);
397}
398
399static inline gdouble
400calc_apparent (WeatherInfo *info)
401{
402 gdouble temp = info->temp;
403 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
404 gdouble apparent = -1000.;
405
406 /*
407 * Wind chill calculations as of 01-Nov-2001
408 * http://www.nws.noaa.gov/om/windchill/index.shtml
409 * Some pages suggest that the formula will soon be adjusted
410 * to account for solar radiation (bright sun vs cloudy sky)
411 */
412 if (temp <= 50.0) {
413 if (wind > 3.0) {
414 gdouble v = pow (wind, 0.16);
415 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
416 } else if (wind >= 0.) {
417 apparent = temp;
418 }
419 }
420 /*
421 * Heat index calculations:
422 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
423 */
424 else if (temp >= 80.0) {
425 if (info->temp >= -500. && info->dew >= -500.) {
426 gdouble humidity = calc_humidity (info->temp, info->dew);
427 gdouble t2 = temp * temp;
428 gdouble h2 = humidity * humidity;
429
430#if 1
431 /*
432 * A really precise formula. Note that overall precision is
433 * constrained by the accuracy of the instruments and that the
434 * we receive the temperature and dewpoints as integers.
435 */
436 gdouble t3 = t2 * temp;
437 gdouble h3 = h2 * temp;
438
439 apparent = 16.923
440 + 0.185212 * temp
441 + 5.37941 * humidity
442 - 0.100254 * temp * humidity
443 + 9.41695e-3 * t2
444 + 7.28898e-3 * h2
445 + 3.45372e-4 * t2 * humidity
446 - 8.14971e-4 * temp * h2
447 + 1.02102e-5 * t2 * h2
448 - 3.8646e-5 * t3
449 + 2.91583e-5 * h3
450 + 1.42721e-6 * t3 * humidity
451 + 1.97483e-7 * temp * h3
452 - 2.18429e-8 * t3 * h2
453 + 8.43296e-10 * t2 * h3
454 - 4.81975e-11 * t3 * h3;
455#else
456 /*
457 * An often cited alternative: values are within 5 degrees for
458 * most ranges between 10% and 70% humidity and to 110 degrees.
459 */
460 apparent = - 42.379
461 + 2.04901523 * temp
462 + 10.14333127 * humidity
463 - 0.22475541 * temp * humidity
464 - 6.83783e-3 * t2
465 - 5.481717e-2 * h2
466 + 1.22874e-3 * t2 * humidity
467 + 8.5282e-4 * temp * h2
468 - 1.99e-6 * t2 * h2;
469#endif
470 }
471 } else {
472 apparent = temp;
473 }
474
475 return apparent;
476}
477
478WeatherInfo *
479_weather_info_fill (WeatherInfo *info,
480 WeatherLocation *location,
481 const WeatherPrefs *prefs,
482 WeatherInfoFunc cb,
483 gpointer data)
484{
485 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
486 ((info != NULL) && (location == NULL)), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (((info == ((void*)0)) && (location != ((void*)0
))) || ((info != ((void*)0)) && (location == ((void*)
0)))) _g_boolean_var_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1))) { } else { g_return_if_fail_warning ("MateWeather"
, ((const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
487 g_return_val_if_fail (prefs != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if (prefs != ((void*)0)) _g_boolean_var_151 = 1; else _g_boolean_var_151
= 0; _g_boolean_var_151; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
488
489 /* FIXME: i'm not sure this works as intended anymore */
490 if (!info) {
491 info = g_new0 (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc0 (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s
); __p; }))
;
492 info->requests_pending = 0;
493 info->location = weather_location_clone (location);
494 } else {
495 location = info->location;
496 if (info->forecast)
497 g_free (info->forecast);
498 info->forecast = NULL((void*)0);
499
500 free_forecast_list (info);
501
502 if (info->radar != NULL((void*)0)) {
503 g_object_unref (info->radar);
504 info->radar = NULL((void*)0);
505 }
506 }
507
508 /* Update in progress */
509 if (!requests_init (info)) {
510 return NULL((void*)0);
511 }
512
513 /* Defaults (just in case...) */
514 /* Well, no just in case anymore. We may actually fail to fetch some
515 * fields. */
516 info->forecast_type = prefs->type;
517
518 info->temperature_unit = prefs->temperature_unit;
519 info->speed_unit = prefs->speed_unit;
520 info->pressure_unit = prefs->pressure_unit;
521 info->distance_unit = prefs->distance_unit;
522
523 info->update = 0;
524 info->sky = -1;
525 info->cond.significant = FALSE(0);
526 info->cond.phenomenon = PHENOMENON_NONE;
527 info->cond.qualifier = QUALIFIER_NONE;
528 info->temp = -1000.0;
529 info->tempMinMaxValid = FALSE(0);
530 info->temp_min = -1000.0;
531 info->temp_max = -1000.0;
532 info->dew = -1000.0;
533 info->wind = -1;
534 info->windspeed = -1;
535 info->pressure = -1.0;
536 info->visibility = -1.0;
537 info->sunriseValid = FALSE(0);
538 info->sunsetValid = FALSE(0);
539 info->moonValid = FALSE(0);
540 info->sunrise = 0;
541 info->sunset = 0;
542 info->moonphase = 0;
543 info->moonlatitude = 0;
544 info->forecast = NULL((void*)0);
545 info->forecast_list = NULL((void*)0);
546 info->radar = NULL((void*)0);
547 info->radar_url = prefs->radar && prefs->radar_custom_url ?
548 g_strdup (prefs->radar_custom_url)g_strdup_inline (prefs->radar_custom_url) : NULL((void*)0);
549 info->finish_cb = cb;
550 info->cb_data = data;
551
552 if (!info->session) {
553 info->session = soup_session_new ();
554 }
555
556 metar_start_open (info);
557 iwin_start_open (info);
558
559 if (prefs->radar) {
560 wx_start_open (info);
561 }
562
563 return info;
564}
565
566void
567weather_info_abort (WeatherInfo *info)
568{
569 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if (info != ((void*)0)) _g_boolean_var_152 = 1; else _g_boolean_var_152
= 0; _g_boolean_var_152; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
570
571 if (info->session) {
572 soup_session_abort (info->session);
573 info->requests_pending = 0;
574 }
575}
576
577WeatherInfo *
578weather_info_clone (const WeatherInfo *info)
579{
580 WeatherInfo *clone;
581
582 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if (info != ((void*)0)) _g_boolean_var_153 = 1; else _g_boolean_var_153
= 0; _g_boolean_var_153; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
583
584 clone = g_new (WeatherInfo, 1)(WeatherInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (WeatherInfo); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
585
586 /* move everything */
587 memmove (clone, info, sizeof (WeatherInfo));
588
589 /* special moves */
590 clone->location = weather_location_clone (info->location);
591 /* This handles null correctly */
592 clone->forecast = g_strdup (info->forecast)g_strdup_inline (info->forecast);
593 clone->radar_url = g_strdup (info->radar_url)g_strdup_inline (info->radar_url);
594
595 if (info->forecast_list) {
596 GSList *p;
597
598 clone->forecast_list = NULL((void*)0);
599 for (p = info->forecast_list; p; p = p->next) {
600 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
601 }
602
603 clone->forecast_list = g_slist_reverse (clone->forecast_list);
604 }
605
606 clone->radar = info->radar;
607 if (clone->radar != NULL((void*)0))
608 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
609
610 return clone;
611}
612
613void
614weather_info_free (WeatherInfo *info)
615{
616 if (!info)
617 return;
618
619 weather_info_abort (info);
620 if (info->session)
621 g_object_unref (info->session);
622
623 weather_location_free (info->location);
624 info->location = NULL((void*)0);
625
626 g_free (info->forecast);
627 info->forecast = NULL((void*)0);
628
629 free_forecast_list (info);
630
631 if (info->radar != NULL((void*)0)) {
632 g_object_unref (info->radar);
633 info->radar = NULL((void*)0);
634 }
635
636 g_free (info);
637}
638
639gboolean
640weather_info_is_valid (WeatherInfo *info)
641{
642 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if (info != ((void*)0)) _g_boolean_var_154 = 1; else _g_boolean_var_154
= 0; _g_boolean_var_154; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
643 return info->valid;
644}
645
646gboolean
647weather_info_network_error (WeatherInfo *info)
648{
649 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if (info != ((void*)0)) _g_boolean_var_155 = 1; else _g_boolean_var_155
= 0; _g_boolean_var_155; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
650 return info->network_error;
651}
652
653void
654weather_info_to_metric (WeatherInfo *info)
655{
656 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if (info != ((void*)0)) _g_boolean_var_156 = 1; else _g_boolean_var_156
= 0; _g_boolean_var_156; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
657
658 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
659 info->speed_unit = SPEED_UNIT_MS;
660 info->pressure_unit = PRESSURE_UNIT_HPA;
661 info->distance_unit = DISTANCE_UNIT_METERS;
662}
663
664void
665weather_info_to_imperial (WeatherInfo *info)
666{
667 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if (info != ((void*)0)) _g_boolean_var_157 = 1; else _g_boolean_var_157
= 0; _g_boolean_var_157; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
668
669 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
670 info->speed_unit = SPEED_UNIT_MPH;
671 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
672 info->distance_unit = DISTANCE_UNIT_MILES;
673}
674
675const WeatherLocation *
676weather_info_get_location (WeatherInfo *info)
677{
678 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if (info != ((void*)0)) _g_boolean_var_158 = 1; else _g_boolean_var_158
= 0; _g_boolean_var_158; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
679 return info->location;
680}
681
682const gchar *
683weather_info_get_location_name (WeatherInfo *info)
684{
685 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if (info != ((void*)0)) _g_boolean_var_159 = 1; else _g_boolean_var_159
= 0; _g_boolean_var_159; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
686 g_return_val_if_fail (info->location != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if (info->location != ((void*)0)) _g_boolean_var_160 = 1
; else _g_boolean_var_160 = 0; _g_boolean_var_160; }), 1))) {
} else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info->location != NULL"); return (((void*
)0)); } } while (0)
;
687 return info->location->name;
688}
689
690const gchar *
691weather_info_get_update (WeatherInfo *info)
692{
693 static gchar buf[200];
694 char *utf8, *timeformat;
695
696 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if (info != ((void*)0)) _g_boolean_var_161 = 1; else _g_boolean_var_161
= 0; _g_boolean_var_161; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
697
698 if (!info->valid)
699 return "-";
700
701 if (info->update != 0) {
702 struct tm tm;
703 localtime_r (&info->update, &tm);
704 /* Translators: this is a format string for strftime
705 * see `man 3 strftime` for more details
706 */
707 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(mateweather_gettext ("%a, %b %d / %H:%M")), -1,
708 NULL((void*)0), NULL((void*)0), NULL((void*)0));
709 if (!timeformat) {
710 strcpy (buf, "???");
711 }
712 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
713 strcpy (buf, "???");
714 }
715 g_free (timeformat);
716
717 /* Convert to UTF-8 */
718 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
719 strcpy (buf, utf8);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
720 g_free (utf8);
721 } else {
722 strncpy (buf, _("Unknown observation time")(mateweather_gettext ("Unknown observation time")), sizeof (buf));
723 buf[sizeof (buf)-1] = '\0';
724 }
725
726 return buf;
727}
728
729const gchar *
730weather_info_get_sky (WeatherInfo *info)
731{
732 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if (info != ((void*)0)) _g_boolean_var_162 = 1; else _g_boolean_var_162
= 0; _g_boolean_var_162; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
733 if (!info->valid)
734 return "-";
735 if (info->sky < 0)
736 return _("Unknown")(mateweather_gettext ("Unknown"));
737 return weather_sky_string (info->sky);
738}
739
740const gchar *
741weather_info_get_conditions (WeatherInfo *info)
742{
743 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if (info != ((void*)0)) _g_boolean_var_163 = 1; else _g_boolean_var_163
= 0; _g_boolean_var_163; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
744 if (!info->valid)
745 return "-";
746 return weather_conditions_string (info->cond);
747}
748
749static const gchar *
750temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round)
751{
752 static gchar buf[100];
753
754 switch (to_unit) {
755 case TEMP_UNIT_FAHRENHEIT:
756 if (!want_round) {
757 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
758 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(mateweather_gettext ("%.1f \302\260F")), temp);
759 } else {
760 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
761 gdouble temp_r;
762
763 feclearexcept(range_problem);
764 temp_r = round (temp);
765 if (fetestexcept(range_problem))
766 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
767 else
768 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
769 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(mateweather_gettext ("%d \302\260F")), (int)temp_r);
770 }
771 break;
772 case TEMP_UNIT_CENTIGRADE:
773 if (!want_round) {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(mateweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
776 } else {
777 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
778 gdouble temp_r;
779
780 feclearexcept(range_problem);
781 temp_r = round (TEMP_F_TO_C (temp)(((temp) - 32.0) * (5.0/9.0)));
782 if (fetestexcept(range_problem))
783 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
784 else
785 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
786 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(mateweather_gettext ("%d \302\260C")), (int)temp_r);
787 }
788 break;
789 case TEMP_UNIT_KELVIN:
790 if (!want_round) {
791 /* Translators: This is the temperature in kelvin */
792 g_snprintf (buf, sizeof (buf), _("%.1f K")(mateweather_gettext ("%.1f K")), TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
793 } else {
794 const int range_problem = FE_INVALID0x01 | FE_DIVBYZERO0x04 | FE_OVERFLOW0x08 | FE_UNDERFLOW0x10;
795 gdouble temp_r;
796
797 feclearexcept(range_problem);
798 temp_r = round (TEMP_F_TO_K (temp)((temp + 459.67) * (5.0/9.0)));
799 if (fetestexcept(range_problem))
800 g_snprintf (buf, sizeof (buf), _("n/a")(mateweather_gettext ("n/a")));
801 else
802 /* Translators: This is the temperature in kelvin */
803 g_snprintf (buf, sizeof (buf), _("%d K")(mateweather_gettext ("%d K")), (int)temp_r);
804 }
805 break;
806
807 case TEMP_UNIT_INVALID:
808 case TEMP_UNIT_DEFAULT:
809 default:
810 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
811 return _("Unknown")(mateweather_gettext ("Unknown"));
812 }
813
814 return buf;
815}
816
817const gchar *
818weather_info_get_temp (WeatherInfo *info)
819{
820 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if (info != ((void*)0)) _g_boolean_var_164 = 1; else _g_boolean_var_164
= 0; _g_boolean_var_164; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
821
822 if (!info->valid)
823 return "-";
824 if (info->temp < -500.0)
825 return _("Unknown")(mateweather_gettext ("Unknown"));
826
827 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
828}
829
830const gchar *
831weather_info_get_temp_min (WeatherInfo *info)
832{
833 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if (info != ((void*)0)) _g_boolean_var_165 = 1; else _g_boolean_var_165
= 0; _g_boolean_var_165; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
834
835 if (!info->valid || !info->tempMinMaxValid)
836 return "-";
837 if (info->temp_min < -500.0)
838 return _("Unknown")(mateweather_gettext ("Unknown"));
839
840 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
841}
842
843const gchar *
844weather_info_get_temp_max (WeatherInfo *info)
845{
846 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if (info != ((void*)0)) _g_boolean_var_166 = 1; else _g_boolean_var_166
= 0; _g_boolean_var_166; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
847
848 if (!info->valid || !info->tempMinMaxValid)
849 return "-";
850 if (info->temp_max < -500.0)
851 return _("Unknown")(mateweather_gettext ("Unknown"));
852
853 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
854}
855
856const gchar *
857weather_info_get_dew (WeatherInfo *info)
858{
859 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if (info != ((void*)0)) _g_boolean_var_167 = 1; else _g_boolean_var_167
= 0; _g_boolean_var_167; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
860
861 if (!info->valid)
862 return "-";
863 if (info->dew < -500.0)
864 return _("Unknown")(mateweather_gettext ("Unknown"));
865
866 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
867}
868
869const gchar *
870weather_info_get_humidity (WeatherInfo *info)
871{
872 static gchar buf[20];
873 gdouble humidity;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if (info != ((void*)0)) _g_boolean_var_168 = 1; else _g_boolean_var_168
= 0; _g_boolean_var_168; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876
877 if (!info->valid)
878 return "-";
879
880 humidity = calc_humidity (info->temp, info->dew);
881 if (humidity < 0.0)
882 return _("Unknown")(mateweather_gettext ("Unknown"));
883
884 /* Translators: This is the humidity in percent */
885 g_snprintf (buf, sizeof (buf), _("%.f%%")(mateweather_gettext ("%.f%%")), humidity);
886 return buf;
887}
888
889const gchar *
890weather_info_get_apparent (WeatherInfo *info)
891{
892 gdouble apparent;
893
894 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if (info != ((void*)0)) _g_boolean_var_169 = 1; else _g_boolean_var_169
= 0; _g_boolean_var_169; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
895 if (!info->valid)
896 return "-";
897
898 apparent = calc_apparent (info);
899 if (apparent < -500.0)
900 return _("Unknown")(mateweather_gettext ("Unknown"));
901
902 return temperature_string (apparent, info->temperature_unit, FALSE(0));
903}
904
905static const gchar *
906windspeed_string (gfloat knots, SpeedUnit to_unit)
907{
908 static gchar buf[100];
909
910 switch (to_unit) {
911 case SPEED_UNIT_KNOTS:
912 /* Translators: This is the wind speed in knots */
913 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(mateweather_gettext ("%0.1f knots")), knots);
914 break;
915 case SPEED_UNIT_MPH:
916 /* Translators: This is the wind speed in miles per hour */
917 g_snprintf (buf, sizeof (buf), _("%.1f mph")(mateweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
918 break;
919 case SPEED_UNIT_KPH:
920 /* Translators: This is the wind speed in kilometers per hour */
921 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(mateweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
922 break;
923 case SPEED_UNIT_MS:
924 /* Translators: This is the wind speed in meters per second */
925 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(mateweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
926 break;
927 case SPEED_UNIT_BFT:
928 /* Translators: This is the wind speed as a Beaufort force factor
929 * (commonly used in nautical wind estimation).
930 */
931 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(mateweather_gettext ("Beaufort force %.1f")),
932 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
933 break;
934 case SPEED_UNIT_INVALID:
935 case SPEED_UNIT_DEFAULT:
936 default:
937 g_warning ("Conversion to illegal speed unit: %d", to_unit);
938 return _("Unknown")(mateweather_gettext ("Unknown"));
939 }
940
941 return buf;
942}
943
944const gchar *
945weather_info_get_wind (WeatherInfo *info)
946{
947 static gchar buf[200];
948
949 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if (info != ((void*)0)) _g_boolean_var_170 = 1; else _g_boolean_var_170
= 0; _g_boolean_var_170; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
950
951 if (!info->valid)
952 return "-";
953 if (info->windspeed < 0.0 || info->wind < 0)
954 return _("Unknown")(mateweather_gettext ("Unknown"));
955 if (info->windspeed == 0.00) {
956 strncpy (buf, _("Calm")(mateweather_gettext ("Calm")), sizeof (buf));
957 buf[sizeof (buf)-1] = '\0';
958 } else {
959 /* Translators: This is 'wind direction' / 'wind speed' */
960 g_snprintf (buf, sizeof (buf), _("%s / %s")(mateweather_gettext ("%s / %s")),
961 weather_wind_direction_string (info->wind),
962 windspeed_string (info->windspeed, info->speed_unit));
963 }
964 return buf;
965}
966
967const gchar *
968weather_info_get_pressure (WeatherInfo *info)
969{
970 static gchar buf[100];
971
972 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_171
; if (info != ((void*)0)) _g_boolean_var_171 = 1; else _g_boolean_var_171
= 0; _g_boolean_var_171; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
973
974 if (!info->valid)
975 return "-";
976 if (info->pressure < 0.0)
977 return _("Unknown")(mateweather_gettext ("Unknown"));
978
979 switch (info->pressure_unit) {
980 case PRESSURE_UNIT_INCH_HG:
981 /* Translators: This is pressure in inches of mercury */
982 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(mateweather_gettext ("%.2f inHg")), info->pressure);
983 break;
984 case PRESSURE_UNIT_MM_HG:
985 /* Translators: This is pressure in millimeters of mercury */
986 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(mateweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
987 break;
988 case PRESSURE_UNIT_KPA:
989 /* Translators: This is pressure in kiloPascals */
990 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(mateweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
991 break;
992 case PRESSURE_UNIT_HPA:
993 /* Translators: This is pressure in hectoPascals */
994 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(mateweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
995 break;
996 case PRESSURE_UNIT_MB:
997 /* Translators: This is pressure in millibars */
998 g_snprintf (buf, sizeof (buf), _("%.2f mb")(mateweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
999 break;
1000 case PRESSURE_UNIT_ATM:
1001 /* Translators: This is pressure in atmospheres */
1002 g_snprintf (buf, sizeof (buf), _("%.3f atm")(mateweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
1003 break;
1004
1005 case PRESSURE_UNIT_INVALID:
1006 case PRESSURE_UNIT_DEFAULT:
1007 default:
1008 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
1009 return _("Unknown")(mateweather_gettext ("Unknown"));
1010 }
1011
1012 return buf;
1013}
1014
1015const gchar *
1016weather_info_get_visibility (WeatherInfo *info)
1017{
1018 static gchar buf[100];
1019
1020 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_172
; if (info != ((void*)0)) _g_boolean_var_172 = 1; else _g_boolean_var_172
= 0; _g_boolean_var_172; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1021
1022 if (!info->valid)
1023 return "-";
1024 if (info->visibility < 0.0)
1025 return _("Unknown")(mateweather_gettext ("Unknown"));
1026
1027 switch (info->distance_unit) {
1028 case DISTANCE_UNIT_MILES:
1029 /* Translators: This is the visibility in miles */
1030 g_snprintf (buf, sizeof (buf), _("%.1f miles")(mateweather_gettext ("%.1f miles")), info->visibility);
1031 break;
1032 case DISTANCE_UNIT_KM:
1033 /* Translators: This is the visibility in kilometers */
1034 g_snprintf (buf, sizeof (buf), _("%.1f km")(mateweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1035 break;
1036 case DISTANCE_UNIT_METERS:
1037 /* Translators: This is the visibility in meters */
1038 g_snprintf (buf, sizeof (buf), _("%.0fm")(mateweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1039 break;
1040
1041 case DISTANCE_UNIT_INVALID:
1042 case DISTANCE_UNIT_DEFAULT:
1043 default:
1044 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1045 return _("Unknown")(mateweather_gettext ("Unknown"));
1046 }
1047
1048 return buf;
1049}
1050
1051const gchar *
1052weather_info_get_sunrise (WeatherInfo *info)
1053{
1054 static gchar buf[200];
1055 struct tm tm;
1056
1057 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_173
; if (info && info->location) _g_boolean_var_173 =
1; else _g_boolean_var_173 = 0; _g_boolean_var_173; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1058
1059 if (!info->location->latlon_valid)
1060 return "-";
1061 if (!info->valid)
1062 return "-";
1063 if (!calc_sun (info))
1064 return "-";
1065
1066 localtime_r (&info->sunrise, &tm);
1067 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1068 return "-";
1069 return buf;
1070}
1071
1072const gchar *
1073weather_info_get_sunset (WeatherInfo *info)
1074{
1075 static gchar buf[200];
1076 struct tm tm;
1077
1078 g_return_val_if_fail (info && info->location, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_174
; if (info && info->location) _g_boolean_var_174 =
1; else _g_boolean_var_174 = 0; _g_boolean_var_174; }), 1)))
{ } else { g_return_if_fail_warning ("MateWeather", ((const char
*) (__func__)), "info && info->location"); return (
((void*)0)); } } while (0)
;
1079
1080 if (!info->location->latlon_valid)
1081 return "-";
1082 if (!info->valid)
1083 return "-";
1084 if (!calc_sun (info))
1085 return "-";
1086
1087 localtime_r (&info->sunset, &tm);
1088 if (strftime (buf, sizeof (buf), _("%H:%M")(mateweather_gettext ("%H:%M")), &tm) <= 0)
1089 return "-";
1090 return buf;
1091}
1092
1093const gchar *
1094weather_info_get_forecast (WeatherInfo *info)
1095{
1096 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_175
; if (info != ((void*)0)) _g_boolean_var_175 = 1; else _g_boolean_var_175
= 0; _g_boolean_var_175; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1097 return info->forecast;
1098}
1099
1100/**
1101 * weather_info_get_forecast_list:
1102 * Returns list of WeatherInfo* objects for the forecast.
1103 * The list is owned by the 'info' object thus is alive as long
1104 * as the 'info'. This list is filled only when requested with
1105 * type FORECAST_LIST and if available for given location.
1106 * The 'update' property is the date/time when the forecast info
1107 * is used for.
1108 **/
1109GSList *
1110weather_info_get_forecast_list (WeatherInfo *info)
1111{
1112 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if (info != ((void*)0)) _g_boolean_var_176 = 1; else _g_boolean_var_176
= 0; _g_boolean_var_176; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1113
1114 if (!info->valid)
1115 return NULL((void*)0);
1116
1117 return info->forecast_list;
1118}
1119
1120GdkPixbufAnimation *
1121weather_info_get_radar (WeatherInfo *info)
1122{
1123 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_177
; if (info != ((void*)0)) _g_boolean_var_177 = 1; else _g_boolean_var_177
= 0; _g_boolean_var_177; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1124 return info->radar;
1125}
1126
1127const gchar *
1128weather_info_get_temp_summary (WeatherInfo *info)
1129{
1130 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if (info != ((void*)0)) _g_boolean_var_178 = 1; else _g_boolean_var_178
= 0; _g_boolean_var_178; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1131
1132 if (!info->valid || info->temp < -500.0)
1133 return "--";
1134
1135 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1136
1137}
1138
1139gchar *
1140weather_info_get_weather_summary (WeatherInfo *info)
1141{
1142 const gchar *buf;
1143
1144 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if (info != ((void*)0)) _g_boolean_var_179 = 1; else _g_boolean_var_179
= 0; _g_boolean_var_179; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1145
1146 if (!info->valid)
1147 return g_strdup (_("Retrieval failed"))g_strdup_inline ((mateweather_gettext ("Retrieval failed")));
1148 buf = weather_info_get_conditions (info);
1149 if (!strcmp (buf, "-"))
1150 buf = weather_info_get_sky (info);
1151 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1152}
1153
1154const gchar *
1155weather_info_get_icon_name (WeatherInfo *info)
1156{
1157 WeatherConditions cond;
1158 WeatherSky sky;
1159 time_t current_time;
1160 gboolean daytime;
1161 gchar* icon;
1162 static gchar icon_buffer[32];
1163 WeatherMoonPhase moonPhase;
1164 WeatherMoonLatitude moonLat;
1165 gint phase;
1166
1167 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if (info != ((void*)0)) _g_boolean_var_180 = 1; else _g_boolean_var_180
= 0; _g_boolean_var_180; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1168
1169 if (!info->valid)
1170 return NULL((void*)0);
1171
1172 cond = info->cond;
1173 sky = info->sky;
1174
1175 if (cond.significant) {
1176 if (cond.phenomenon != PHENOMENON_NONE &&
1177 cond.qualifier == QUALIFIER_THUNDERSTORM)
1178 return "weather-storm";
1179
1180 switch (cond.phenomenon) {
1181 case PHENOMENON_INVALID:
1182 case PHENOMENON_LAST:
1183 case PHENOMENON_NONE:
1184 break;
1185
1186 case PHENOMENON_DRIZZLE:
1187 case PHENOMENON_RAIN:
1188 case PHENOMENON_UNKNOWN_PRECIPITATION:
1189 case PHENOMENON_HAIL:
1190 case PHENOMENON_SMALL_HAIL:
1191 return "weather-showers";
1192
1193 case PHENOMENON_SNOW:
1194 case PHENOMENON_SNOW_GRAINS:
1195 case PHENOMENON_ICE_PELLETS:
1196 case PHENOMENON_ICE_CRYSTALS:
1197 return "weather-snow";
1198
1199 case PHENOMENON_TORNADO:
1200 case PHENOMENON_SQUALL:
1201 return "weather-storm";
1202
1203 case PHENOMENON_MIST:
1204 case PHENOMENON_FOG:
1205 case PHENOMENON_SMOKE:
1206 case PHENOMENON_VOLCANIC_ASH:
1207 case PHENOMENON_SAND:
1208 case PHENOMENON_HAZE:
1209 case PHENOMENON_SPRAY:
1210 case PHENOMENON_DUST:
1211 case PHENOMENON_SANDSTORM:
1212 case PHENOMENON_DUSTSTORM:
1213 case PHENOMENON_FUNNEL_CLOUD:
1214 case PHENOMENON_DUST_WHIRLS:
1215 return "weather-fog";
1216 }
1217 }
1218
1219 if (info->midnightSun ||
1220 (!info->sunriseValid && !info->sunsetValid))
1221 daytime = TRUE(!(0));
1222 else if (info->polarNight)
1223 daytime = FALSE(0);
1224 else {
1225 current_time = time (NULL((void*)0));
1226 daytime =
1227 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1228 ( !info->sunsetValid || (current_time < info->sunset) );
1229 }
1230
1231 switch (sky) {
1232 case SKY_INVALID:
1233 case SKY_LAST:
1234 case SKY_CLEAR:
1235 if (daytime)
1236 return "weather-clear";
1237 else {
1238 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1239 break;
1240 }
1241
1242 case SKY_BROKEN:
1243 case SKY_SCATTERED:
1244 case SKY_FEW:
1245 if (daytime)
1246 return "weather-few-clouds";
1247 else {
1248 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1249 break;
1250 }
1251
1252 case SKY_OVERCAST:
1253 return "weather-overcast";
1254
1255 default: /* unrecognized */
1256 return NULL((void*)0);
1257 }
1258
1259 /*
1260 * A phase-of-moon icon is to be returned.
1261 * Determine which one based on the moon's location
1262 */
1263 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1264 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1265 if (phase == MOON_PHASES36) {
1266 phase = 0;
1267 } else if (phase > 0 &&
1268 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1269 < moonLat)) {
1270 /*
1271 * Locations south of the moon's latitude will see the moon in the
1272 * northern sky. The moon waxes and wanes from left to right
1273 * so we reference an icon running in the opposite direction.
1274 */
1275 phase = MOON_PHASES36 - phase;
1276 }
1277
1278 /*
1279 * If the moon is not full then append the angle to the icon string.
1280 * Note that an icon by this name is not required to exist:
1281 * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1282 * the full moon image.
1283 */
1284 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1285 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1286 "-%03d", phase * 360 / MOON_PHASES36);
1287 }
1288 }
1289 return icon_buffer;
1290}
1291
1292static gboolean
1293temperature_value (gdouble temp_f,
1294 TempUnit to_unit,
1295 gdouble *value,
1296 TempUnit def_unit)
1297{
1298 gboolean ok = TRUE(!(0));
1299
1300 *value = 0.0;
1301 if (temp_f < -500.0)
1302 return FALSE(0);
1303
1304 if (to_unit == TEMP_UNIT_DEFAULT)
1305 to_unit = def_unit;
1306
1307 switch (to_unit) {
1308 case TEMP_UNIT_FAHRENHEIT:
1309 *value = temp_f;
1310 break;
1311 case TEMP_UNIT_CENTIGRADE:
1312 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * (5.0/9.0));
1313 break;
1314 case TEMP_UNIT_KELVIN:
1315 *value = TEMP_F_TO_K (temp_f)((temp_f + 459.67) * (5.0/9.0));
1316 break;
1317 case TEMP_UNIT_INVALID:
1318 case TEMP_UNIT_DEFAULT:
1319 default:
1320 ok = FALSE(0);
1321 break;
1322 }
1323
1324 return ok;
1325}
1326
1327static gboolean
1328speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1329{
1330 gboolean ok = TRUE(!(0));
1331
1332 *value = -1.0;
1333
1334 if (knots < 0.0)
1335 return FALSE(0);
1336
1337 if (to_unit == SPEED_UNIT_DEFAULT)
1338 to_unit = def_unit;
1339
1340 switch (to_unit) {
1341 case SPEED_UNIT_KNOTS:
1342 *value = knots;
1343 break;
1344 case SPEED_UNIT_MPH:
1345 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1346 break;
1347 case SPEED_UNIT_KPH:
1348 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1349 break;
1350 case SPEED_UNIT_MS:
1351 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1352 break;
1353 case SPEED_UNIT_BFT:
1354 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1355 break;
1356 case SPEED_UNIT_INVALID:
1357 case SPEED_UNIT_DEFAULT:
1358 default:
1359 ok = FALSE(0);
1360 break;
1361 }
1362
1363 return ok;
1364}
1365
1366static gboolean
1367pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1368{
1369 gboolean ok = TRUE(!(0));
1370
1371 *value = -1.0;
1372
1373 if (inHg < 0.0)
1374 return FALSE(0);
1375
1376 if (to_unit == PRESSURE_UNIT_DEFAULT)
1377 to_unit = def_unit;
1378
1379 switch (to_unit) {
1380 case PRESSURE_UNIT_INCH_HG:
1381 *value = inHg;
1382 break;
1383 case PRESSURE_UNIT_MM_HG:
1384 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1385 break;
1386 case PRESSURE_UNIT_KPA:
1387 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1388 break;
1389 case PRESSURE_UNIT_HPA:
1390 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1391 break;
1392 case PRESSURE_UNIT_MB:
1393 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1394 break;
1395 case PRESSURE_UNIT_ATM:
1396 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1397 break;
1398 case PRESSURE_UNIT_INVALID:
1399 case PRESSURE_UNIT_DEFAULT:
1400 default:
1401 ok = FALSE(0);
1402 break;
1403 }
1404
1405 return ok;
1406}
1407
1408static gboolean
1409distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1410{
1411 gboolean ok = TRUE(!(0));
1412
1413 *value = -1.0;
1414
1415 if (miles < 0.0)
1416 return FALSE(0);
1417
1418 if (to_unit == DISTANCE_UNIT_DEFAULT)
1419 to_unit = def_unit;
1420
1421 switch (to_unit) {
1422 case DISTANCE_UNIT_MILES:
1423 *value = miles;
1424 break;
1425 case DISTANCE_UNIT_KM:
1426 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1427 break;
1428 case DISTANCE_UNIT_METERS:
1429 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1430 break;
1431 case DISTANCE_UNIT_INVALID:
1432 case DISTANCE_UNIT_DEFAULT:
1433 default:
1434 ok = FALSE(0);
1435 break;
1436 }
1437
1438 return ok;
1439}
1440
1441gboolean
1442weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1443{
1444 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if (info != ((void*)0)) _g_boolean_var_181 = 1; else _g_boolean_var_181
= 0; _g_boolean_var_181; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1445 g_return_val_if_fail (sky != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if (sky != ((void*)0)) _g_boolean_var_182 = 1; else _g_boolean_var_182
= 0; _g_boolean_var_182; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1446
1447 if (!info->valid)
1448 return FALSE(0);
1449
1450 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1451 return FALSE(0);
1452
1453 *sky = info->sky;
1454
1455 return TRUE(!(0));
1456}
1457
1458gboolean
1459weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1460{
1461 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if (info != ((void*)0)) _g_boolean_var_183 = 1; else _g_boolean_var_183
= 0; _g_boolean_var_183; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1462 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (phenomenon != ((void*)0)) _g_boolean_var_184 = 1; else _g_boolean_var_184
= 0; _g_boolean_var_184; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1463 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if (qualifier != ((void*)0)) _g_boolean_var_185 = 1; else _g_boolean_var_185
= 0; _g_boolean_var_185; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1464
1465 if (!info->valid)
1466 return FALSE(0);
1467
1468 if (!info->cond.significant)
1469 return FALSE(0);
1470
1471 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1472 info->cond.phenomenon < PHENOMENON_LAST &&
1473 info->cond.qualifier > QUALIFIER_INVALID &&
1474 info->cond.qualifier < QUALIFIER_LAST))
1475 return FALSE(0);
1476
1477 *phenomenon = info->cond.phenomenon;
1478 *qualifier = info->cond.qualifier;
1479
1480 return TRUE(!(0));
1481}
1482
1483gboolean
1484weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1485{
1486 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if (info != ((void*)0)) _g_boolean_var_186 = 1; else _g_boolean_var_186
= 0; _g_boolean_var_186; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1487 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if (value != ((void*)0)) _g_boolean_var_187 = 1; else _g_boolean_var_187
= 0; _g_boolean_var_187; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1488
1489 if (!info->valid)
1490 return FALSE(0);
1491
1492 return temperature_value (info->temp, unit, value, info->temperature_unit);
1493}
1494
1495gboolean
1496weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1497{
1498 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if (info != ((void*)0)) _g_boolean_var_188 = 1; else _g_boolean_var_188
= 0; _g_boolean_var_188; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1499 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if (value != ((void*)0)) _g_boolean_var_189 = 1; else _g_boolean_var_189
= 0; _g_boolean_var_189; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1500
1501 if (!info->valid || !info->tempMinMaxValid)
1502 return FALSE(0);
1503
1504 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1505}
1506
1507gboolean
1508weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1509{
1510 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if (info != ((void*)0)) _g_boolean_var_190 = 1; else _g_boolean_var_190
= 0; _g_boolean_var_190; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1511 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if (value != ((void*)0)) _g_boolean_var_191 = 1; else _g_boolean_var_191
= 0; _g_boolean_var_191; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1512
1513 if (!info->valid || !info->tempMinMaxValid)
1514 return FALSE(0);
1515
1516 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1517}
1518
1519gboolean
1520weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1521{
1522 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if (info != ((void*)0)) _g_boolean_var_192 = 1; else _g_boolean_var_192
= 0; _g_boolean_var_192; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1523 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if (value != ((void*)0)) _g_boolean_var_193 = 1; else _g_boolean_var_193
= 0; _g_boolean_var_193; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1524
1525 if (!info->valid)
1526 return FALSE(0);
1527
1528 return temperature_value (info->dew, unit, value, info->temperature_unit);
1529}
1530
1531gboolean
1532weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1533{
1534 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if (info != ((void*)0)) _g_boolean_var_194 = 1; else _g_boolean_var_194
= 0; _g_boolean_var_194; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1535 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if (value != ((void*)0)) _g_boolean_var_195 = 1; else _g_boolean_var_195
= 0; _g_boolean_var_195; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1536
1537 if (!info->valid)
1538 return FALSE(0);
1539
1540 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1541}
1542
1543gboolean
1544weather_info_get_value_update (WeatherInfo *info, time_t *value)
1545{
1546 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if (info != ((void*)0)) _g_boolean_var_196 = 1; else _g_boolean_var_196
= 0; _g_boolean_var_196; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1547 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if (value != ((void*)0)) _g_boolean_var_197 = 1; else _g_boolean_var_197
= 0; _g_boolean_var_197; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1548
1549 if (!info->valid)
1550 return FALSE(0);
1551
1552 *value = info->update;
1553
1554 return TRUE(!(0));
1555}
1556
1557gboolean
1558weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1559{
1560 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if (info != ((void*)0)) _g_boolean_var_198 = 1; else _g_boolean_var_198
= 0; _g_boolean_var_198; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1561 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if (value != ((void*)0)) _g_boolean_var_199 = 1; else _g_boolean_var_199
= 0; _g_boolean_var_199; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1562
1563 if (!info->valid || !info->sunriseValid)
1564 return FALSE(0);
1565
1566 *value = info->sunrise;
1567
1568 return TRUE(!(0));
1569}
1570
1571gboolean
1572weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1573{
1574 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if (info != ((void*)0)) _g_boolean_var_200 = 1; else _g_boolean_var_200
= 0; _g_boolean_var_200; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1575 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if (value != ((void*)0)) _g_boolean_var_201 = 1; else _g_boolean_var_201
= 0; _g_boolean_var_201; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1576
1577 if (!info->valid || !info->sunsetValid)
1578 return FALSE(0);
1579
1580 *value = info->sunset;
1581
1582 return TRUE(!(0));
1583}
1584
1585gboolean
1586weather_info_get_value_moonphase (WeatherInfo *info,
1587 WeatherMoonPhase *value,
1588 WeatherMoonLatitude *lat)
1589{
1590 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (info != ((void*)0)) _g_boolean_var_202 = 1; else _g_boolean_var_202
= 0; _g_boolean_var_202; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1591 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if (value != ((void*)0)) _g_boolean_var_203 = 1; else _g_boolean_var_203
= 0; _g_boolean_var_203; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1592
1593 if (!info->valid || !info->moonValid)
1594 return FALSE(0);
1595
1596 *value = info->moonphase;
1597 *lat = info->moonlatitude;
1598
1599 return TRUE(!(0));
1600}
1601
1602gboolean
1603weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1604{
1605 gboolean res = FALSE(0);
1606
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if (info != ((void*)0)) _g_boolean_var_204 = 1; else _g_boolean_var_204
= 0; _g_boolean_var_204; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (speed != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if (speed != ((void*)0)) _g_boolean_var_205 = 1; else _g_boolean_var_205
= 0; _g_boolean_var_205; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1609 g_return_val_if_fail (direction != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (direction != ((void*)0)) _g_boolean_var_206 = 1; else _g_boolean_var_206
= 0; _g_boolean_var_206; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1610
1611 if (!info->valid)
1612 return FALSE(0);
1613
1614 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1615 return FALSE(0);
1616
1617 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1618 *direction = info->wind;
1619
1620 return res;
1621}
1622
1623gboolean
1624weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1625{
1626 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if (info != ((void*)0)) _g_boolean_var_207 = 1; else _g_boolean_var_207
= 0; _g_boolean_var_207; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1627 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if (value != ((void*)0)) _g_boolean_var_208 = 1; else _g_boolean_var_208
= 0; _g_boolean_var_208; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1628
1629 if (!info->valid)
1630 return FALSE(0);
1631
1632 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1633}
1634
1635gboolean
1636weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1637{
1638 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if (info != ((void*)0)) _g_boolean_var_209 = 1; else _g_boolean_var_209
= 0; _g_boolean_var_209; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1639 g_return_val_if_fail (value != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if (value != ((void*)0)) _g_boolean_var_210 = 1; else _g_boolean_var_210
= 0; _g_boolean_var_210; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1640
1641 if (!info->valid)
1642 return FALSE(0);
1643
1644 return distance_value (info->visibility, unit, value, info->distance_unit);
1645}
1646
1647/**
1648 * weather_info_get_upcoming_moonphases:
1649 * @info: WeatherInfo containing the time_t of interest
1650 * @phases: An array of four time_t values that will hold the returned values.
1651 * The values are estimates of the time of the next new, quarter, full and
1652 * three-quarter moons.
1653 *
1654 * Returns: gboolean indicating success or failure
1655 */
1656gboolean
1657weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1658{
1659 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if (info != ((void*)0)) _g_boolean_var_211 = 1; else _g_boolean_var_211
= 0; _g_boolean_var_211; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1660 g_return_val_if_fail (phases != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if (phases != ((void*)0)) _g_boolean_var_212 = 1; else _g_boolean_var_212
= 0; _g_boolean_var_212; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1661
1662 return calc_moon_phases(info, phases);
1663}
1664
1665static void
1666_weather_internal_check (void)
1667{
1668 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) _g_boolean_var_213 = 1; else _g_boolean_var_213
= 0; _g_boolean_var_213; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1668, ((const char*) (__func__)
), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"); } while
(0)
;
1669 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST)
_g_boolean_var_214 = 1; else _g_boolean_var_214 = 0; _g_boolean_var_214
; }), 1)) ; else g_assertion_message_expr ("MateWeather", "weather.c"
, 1669, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1670 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((sizeof (conditions_str) / sizeof ((conditions_str)[0])
) == PHENOMENON_LAST) _g_boolean_var_215 = 1; else _g_boolean_var_215
= 0; _g_boolean_var_215; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1670, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"); } while
(0)
;
1671 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if ((sizeof (conditions_str[0]) / sizeof ((conditions_str[0
])[0])) == QUALIFIER_LAST) _g_boolean_var_216 = 1; else _g_boolean_var_216
= 0; _g_boolean_var_216; }), 1)) ; else g_assertion_message_expr
("MateWeather", "weather.c", 1671, ((const char*) (__func__)
), "G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1672}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/report-d766a0.html b/2023-09-01-181303-5846-1@58a183825058_master/report-d766a0.html new file mode 100644 index 00000000..fae1607a --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/report-d766a0.html @@ -0,0 +1,1245 @@ + + + +weather-metar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:weather-metar.c
Warning:line 454, column 5
Value stored to 'i' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name weather-metar.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libmateweather -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-2.4 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="MateWeather" -D MATELOCALEDIR="/usr/local/share/locale" -D MATEWEATHER_XML_LOCATION_DIR="/usr/local/share/libmateweather" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/libmateweather -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-09-01-181303-5846-1 -x c weather-metar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather-metar.c - Weather server functions (METAR)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <regex.h>
27
28#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
29#include "weather.h"
30#include "weather-priv.h"
31
32enum {
33 TIME_RE,
34 WIND_RE,
35 VIS_RE,
36 COND_RE,
37 CLOUD_RE,
38 TEMP_RE,
39 PRES_RE,
40
41 RE_NUM
42};
43
44/* Return time of weather report as secs since epoch UTC */
45static time_t
46make_time (gint utcDate, gint utcHour, gint utcMin)
47{
48 const time_t now = time (NULL((void*)0));
49 struct tm tm;
50
51 localtime_r (&now, &tm);
52
53 /* If last reading took place just before midnight UTC on the
54 * first, adjust the date downward to allow for the month
55 * change-over. This ASSUMES that the reading won't be more than
56 * 24 hrs old! */
57 if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) {
58 tm.tm_mday = 0; /* mktime knows this is the last day of the previous
59 * month. */
60 } else {
61 tm.tm_mday = utcDate;
62 }
63 tm.tm_hour = utcHour;
64 tm.tm_min = utcMin;
65 tm.tm_sec = 0;
66
67 /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */
68#ifdef HAVE_TM_TM_GMOFF1
69 return tm.tm_gmtoff + mktime (&tm);
70#elif defined HAVE_TIMEZONE
71 return timezone + mktime (&tm);
72#endif
73}
74
75static void
76metar_tok_time (gchar *tokp, WeatherInfo *info)
77{
78 gint day, hr, min;
79
80 sscanf (tokp, "%2u%2u%2u", &day, &hr, &min);
81 info->update = make_time (day, hr, min);
82}
83
84static void
85metar_tok_wind (gchar *tokp, WeatherInfo *info)
86{
87 gchar sdir[4], sspd[4], sgust[4];
88 gint dir, spd = -1;
89 gchar *gustp;
90 size_t glen;
91
92 strncpy (sdir, tokp, 3);
93 sdir[3] = 0;
94 dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir);
95
96 memset (sspd, 0, sizeof (sspd));
97 glen = strspn (tokp + 3, CONST_DIGITS"0123456789");
98 strncpy (sspd, tokp + 3, glen);
99 spd = atoi (sspd);
100 tokp += glen + 3;
101
102 gustp = strchr (tokp, 'G');
103 if (gustp) {
104 memset (sgust, 0, sizeof (sgust));
105 glen = strspn (gustp + 1, CONST_DIGITS"0123456789");
106 strncpy (sgust, gustp + 1, glen);
107 tokp = gustp + 1 + glen;
108 }
109
110 if (!strcmp (tokp, "MPS"))
111 info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd)(((WeatherWindSpeed)spd) / 0.514444);
112 else
113 info->windspeed = (WeatherWindSpeed)spd;
114
115 if ((349 <= dir) || (dir <= 11))
116 info->wind = WIND_N;
117 else if ((12 <= dir) && (dir <= 33))
118 info->wind = WIND_NNE;
119 else if ((34 <= dir) && (dir <= 56))
120 info->wind = WIND_NE;
121 else if ((57 <= dir) && (dir <= 78))
122 info->wind = WIND_ENE;
123 else if ((79 <= dir) && (dir <= 101))
124 info->wind = WIND_E;
125 else if ((102 <= dir) && (dir <= 123))
126 info->wind = WIND_ESE;
127 else if ((124 <= dir) && (dir <= 146))
128 info->wind = WIND_SE;
129 else if ((147 <= dir) && (dir <= 168))
130 info->wind = WIND_SSE;
131 else if ((169 <= dir) && (dir <= 191))
132 info->wind = WIND_S;
133 else if ((192 <= dir) && (dir <= 213))
134 info->wind = WIND_SSW;
135 else if ((214 <= dir) && (dir <= 236))
136 info->wind = WIND_SW;
137 else if ((237 <= dir) && (dir <= 258))
138 info->wind = WIND_WSW;
139 else if ((259 <= dir) && (dir <= 281))
140 info->wind = WIND_W;
141 else if ((282 <= dir) && (dir <= 303))
142 info->wind = WIND_WNW;
143 else if ((304 <= dir) && (dir <= 326))
144 info->wind = WIND_NW;
145 else if ((327 <= dir) && (dir <= 348))
146 info->wind = WIND_NNW;
147}
148
149static void
150metar_tok_vis (gchar *tokp, WeatherInfo *info)
151{
152 gchar *pfrac, *pend, *psp;
153 gchar sval[6];
154 gint num, den, val;
155
156 memset (sval, 0, sizeof (sval));
157
158 if (!strcmp (tokp,"CAVOK")) {
159 // "Ceiling And Visibility OK": visibility >= 10 KM
160 info->visibility=10000. / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
161 info->sky = SKY_CLEAR;
162 } else if (0 != (pend = strstr (tokp, "SM"))) {
163 // US observation: field ends with "SM"
164 pfrac = strchr (tokp, '/');
165 if (pfrac) {
166 if (*tokp == 'M') {
167 info->visibility = 0.001;
168 } else {
169 num = (*(pfrac - 1) - '0');
170 strncpy (sval, pfrac + 1, pend - pfrac - 1);
171 den = atoi (sval);
172 info->visibility =
173 ((WeatherVisibility)num / ((WeatherVisibility)den));
174
175 psp = strchr (tokp, ' ');
176 if (psp) {
177 *psp = '\0';
178 val = atoi (tokp);
179 info->visibility += (WeatherVisibility)val;
180 }
181 }
182 } else {
183 strncpy (sval, tokp, pend - tokp);
184 val = atoi (sval);
185 info->visibility = (WeatherVisibility)val;
186 }
187 } else {
188 // International observation: NNNN(DD NNNNDD)?
189 // For now: use only the minimum visibility and ignore its direction
190 strncpy (sval, tokp, strspn (tokp, CONST_DIGITS"0123456789"));
191 val = atoi (sval);
192 info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.)(((1.) * 1.609344) * 1000);
193 }
194}
195
196static void
197metar_tok_cloud (gchar *tokp, WeatherInfo *info)
198{
199 gchar stype[4], salt[4];
200
201 strncpy (stype, tokp, 3);
202 stype[3] = 0;
203 if (strlen (tokp) == 6) {
204 strncpy (salt, tokp + 3, 3);
205 salt[3] = 0;
206 }
207
208 if (!strcmp (stype, "CLR")) {
209 info->sky = SKY_CLEAR;
210 } else if (!strcmp (stype, "SKC")) {
211 info->sky = SKY_CLEAR;
212 } else if (!strcmp (stype, "NSC")) {
213 info->sky = SKY_CLEAR;
214 } else if (!strcmp (stype, "BKN")) {
215 info->sky = SKY_BROKEN;
216 } else if (!strcmp (stype, "SCT")) {
217 info->sky = SKY_SCATTERED;
218 } else if (!strcmp (stype, "FEW")) {
219 info->sky = SKY_FEW;
220 } else if (!strcmp (stype, "OVC")) {
221 info->sky = SKY_OVERCAST;
222 }
223}
224
225static void
226metar_tok_pres (gchar *tokp, WeatherInfo *info)
227{
228 if (*tokp == 'A') {
229 gchar sintg[3], sfract[3];
230 gint intg, fract;
231
232 strncpy (sintg, tokp + 1, 2);
233 sintg[2] = 0;
234 intg = atoi (sintg);
235
236 strncpy (sfract, tokp + 3, 2);
237 sfract[2] = 0;
238 fract = atoi (sfract);
239
240 info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0);
241 } else { /* *tokp == 'Q' */
242 gchar spres[5];
243 gint pres;
244
245 strncpy (spres, tokp + 1, 4);
246 spres[4] = 0;
247 pres = atoi (spres);
248
249 info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres)(((WeatherPressure)pres) * 0.029533373);
250 }
251}
252
253static void
254metar_tok_temp (gchar *tokp, WeatherInfo *info)
255{
256 gchar *ptemp, *pdew, *psep;
257
258 psep = strchr (tokp, '/');
259 *psep = 0;
260 ptemp = tokp;
261 pdew = psep + 1;
262
263 info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1))(((-atoi (ptemp + 1)) * (9.0/5.0)) + 32.0)
264 : TEMP_C_TO_F (atoi (ptemp))(((atoi (ptemp)) * (9.0/5.0)) + 32.0);
265 if (*pdew) {
266 info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1))(((-atoi (pdew + 1)) * (9.0/5.0)) + 32.0)
267 : TEMP_C_TO_F (atoi (pdew))(((atoi (pdew)) * (9.0/5.0)) + 32.0);
268 } else {
269 info->dew = -1000.0;
270 }
271}
272
273static void
274metar_tok_cond (gchar *tokp, WeatherInfo *info)
275{
276 gchar squal[3], sphen[4];
277 gchar *pphen;
278
279 if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-')))
280 ++tokp; /* FIX */
281
282 if ((*tokp == '+') || (*tokp == '-'))
283 pphen = tokp + 1;
284 else if (strlen (tokp) < 4)
285 pphen = tokp;
286 else
287 pphen = tokp + 2;
288
289 memset (squal, 0, sizeof (squal));
290 strncpy (squal, tokp, pphen - tokp);
291 squal[pphen - tokp] = 0;
292
293 memset (sphen, 0, sizeof (sphen));
294 strncpy (sphen, pphen, sizeof (sphen));
295 sphen[sizeof (sphen)-1] = '\0';
296
297 /* Defaults */
298 info->cond.qualifier = QUALIFIER_NONE;
299 info->cond.phenomenon = PHENOMENON_NONE;
300 info->cond.significant = FALSE(0);
301
302 if (!strcmp (squal, "")) {
303 info->cond.qualifier = QUALIFIER_MODERATE;
304 } else if (!strcmp (squal, "-")) {
305 info->cond.qualifier = QUALIFIER_LIGHT;
306 } else if (!strcmp (squal, "+")) {
307 info->cond.qualifier = QUALIFIER_HEAVY;
308 } else if (!strcmp (squal, "VC")) {
309 info->cond.qualifier = QUALIFIER_VICINITY;
310 } else if (!strcmp (squal, "MI")) {
311 info->cond.qualifier = QUALIFIER_SHALLOW;
312 } else if (!strcmp (squal, "BC")) {
313 info->cond.qualifier = QUALIFIER_PATCHES;
314 } else if (!strcmp (squal, "PR")) {
315 info->cond.qualifier = QUALIFIER_PARTIAL;
316 } else if (!strcmp (squal, "TS")) {
317 info->cond.qualifier = QUALIFIER_THUNDERSTORM;
318 } else if (!strcmp (squal, "BL")) {
319 info->cond.qualifier = QUALIFIER_BLOWING;
320 } else if (!strcmp (squal, "SH")) {
321 info->cond.qualifier = QUALIFIER_SHOWERS;
322 } else if (!strcmp (squal, "DR")) {
323 info->cond.qualifier = QUALIFIER_DRIFTING;
324 } else if (!strcmp (squal, "FZ")) {
325 info->cond.qualifier = QUALIFIER_FREEZING;
326 } else {
327 return;
328 }
329
330 if (!strcmp (sphen, "DZ")) {
331 info->cond.phenomenon = PHENOMENON_DRIZZLE;
332 } else if (!strcmp (sphen, "RA")) {
333 info->cond.phenomenon = PHENOMENON_RAIN;
334 } else if (!strcmp (sphen, "SN")) {
335 info->cond.phenomenon = PHENOMENON_SNOW;
336 } else if (!strcmp (sphen, "SG")) {
337 info->cond.phenomenon = PHENOMENON_SNOW_GRAINS;
338 } else if (!strcmp (sphen, "IC")) {
339 info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS;
340 } else if (!strcmp (sphen, "PE")) {
341 info->cond.phenomenon = PHENOMENON_ICE_PELLETS;
342 } else if (!strcmp (sphen, "GR")) {
343 info->cond.phenomenon = PHENOMENON_HAIL;
344 } else if (!strcmp (sphen, "GS")) {
345 info->cond.phenomenon = PHENOMENON_SMALL_HAIL;
346 } else if (!strcmp (sphen, "UP")) {
347 info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION;
348 } else if (!strcmp (sphen, "BR")) {
349 info->cond.phenomenon = PHENOMENON_MIST;
350 } else if (!strcmp (sphen, "FG")) {
351 info->cond.phenomenon = PHENOMENON_FOG;
352 } else if (!strcmp (sphen, "FU")) {
353 info->cond.phenomenon = PHENOMENON_SMOKE;
354 } else if (!strcmp (sphen, "VA")) {
355 info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH;
356 } else if (!strcmp (sphen, "SA")) {
357 info->cond.phenomenon = PHENOMENON_SAND;
358 } else if (!strcmp (sphen, "HZ")) {
359 info->cond.phenomenon = PHENOMENON_HAZE;
360 } else if (!strcmp (sphen, "PY")) {
361 info->cond.phenomenon = PHENOMENON_SPRAY;
362 } else if (!strcmp (sphen, "DU")) {
363 info->cond.phenomenon = PHENOMENON_DUST;
364 } else if (!strcmp (sphen, "SQ")) {
365 info->cond.phenomenon = PHENOMENON_SQUALL;
366 } else if (!strcmp (sphen, "SS")) {
367 info->cond.phenomenon = PHENOMENON_SANDSTORM;
368 } else if (!strcmp (sphen, "DS")) {
369 info->cond.phenomenon = PHENOMENON_DUSTSTORM;
370 } else if (!strcmp (sphen, "PO")) {
371 info->cond.phenomenon = PHENOMENON_DUST_WHIRLS;
372 } else if (!strcmp (sphen, "+FC")) {
373 info->cond.phenomenon = PHENOMENON_TORNADO;
374 } else if (!strcmp (sphen, "FC")) {
375 info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD;
376 } else {
377 return;
378 }
379
380 if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE))
381 info->cond.significant = TRUE(!(0));
382}
383
384#define TIME_RE_STR"([0-9]{6})Z" "([0-9]{6})Z"
385#define WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)"
386#define VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \
387 "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \
388 "CAVOK"
389#define COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)"
390#define CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)"
391#define TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)"
392#define PRES_RE_STR"(A|Q)([0-9]{4})" "(A|Q)([0-9]{4})"
393
394/* POSIX regular expressions do not allow us to express "match whole words
395 * only" in a simple way, so we have to wrap them all into
396 * (^| )(...regex...)( |$)
397 */
398#define RE_PREFIX"(^| )(" "(^| )("
399#define RE_SUFFIX")( |$)" ")( |$)"
400
401static regex_t metar_re[RE_NUM];
402static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info);
403
404static void
405metar_init_re (void)
406{
407 static gboolean initialized = FALSE(0);
408 if (initialized)
409 return;
410 initialized = TRUE(!(0));
411
412 regcomp (&metar_re[TIME_RE], RE_PREFIX"(^| )(" TIME_RE_STR"([0-9]{6})Z" RE_SUFFIX")( |$)", REG_EXTENDED1);
413 regcomp (&metar_re[WIND_RE], RE_PREFIX"(^| )(" WIND_RE_STR"(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" RE_SUFFIX")( |$)", REG_EXTENDED1);
414 regcomp (&metar_re[VIS_RE], RE_PREFIX"(^| )(" VIS_RE_STR"((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|"
"CAVOK"
RE_SUFFIX")( |$)", REG_EXTENDED1);
415 regcomp (&metar_re[COND_RE], RE_PREFIX"(^| )(" COND_RE_STR"(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" RE_SUFFIX")( |$)", REG_EXTENDED1);
416 regcomp (&metar_re[CLOUD_RE], RE_PREFIX"(^| )(" CLOUD_RE_STR"((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
417 regcomp (&metar_re[TEMP_RE], RE_PREFIX"(^| )(" TEMP_RE_STR"(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" RE_SUFFIX")( |$)", REG_EXTENDED1);
418 regcomp (&metar_re[PRES_RE], RE_PREFIX"(^| )(" PRES_RE_STR"(A|Q)([0-9]{4})" RE_SUFFIX")( |$)", REG_EXTENDED1);
419
420 metar_f[TIME_RE] = metar_tok_time;
421 metar_f[WIND_RE] = metar_tok_wind;
422 metar_f[VIS_RE] = metar_tok_vis;
423 metar_f[COND_RE] = metar_tok_cond;
424 metar_f[CLOUD_RE] = metar_tok_cloud;
425 metar_f[TEMP_RE] = metar_tok_temp;
426 metar_f[PRES_RE] = metar_tok_pres;
427}
428
429gboolean
430metar_parse (gchar *metar, WeatherInfo *info)
431{
432 gchar *p;
433 //gchar *rmk;
434 gint i, i2;
435 regmatch_t rm, rm2;
436 gchar *tokp;
437
438 g_return_val_if_fail (info != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (info != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
439 g_return_val_if_fail (metar != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (metar != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "metar != NULL")
; return ((0)); } } while (0)
;
440
441 metar_init_re ();
442
443 /*
444 * Force parsing to end at "RMK" field. This prevents a subtle
445 * problem when info within the remark happens to match an earlier state
446 * and, as a result, throws off all the remaining expression
447 */
448 if (0 != (p = strstr (metar, " RMK "))) {
449 *p = '\0';
450 //rmk = p + 5; // uncomment this if RMK data becomes useful
451 }
452
453 p = metar;
454 i = TIME_RE;
Value stored to 'i' is never read
455 while (*p) {
456
457 i2 = RE_NUM;
458 rm2.rm_so = strlen (p);
459 rm2.rm_eo = rm2.rm_so;
460
461 for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) {
462 if (0 == regexec (&metar_re[i], p, 1, &rm, 0)
463 && rm.rm_so < rm2.rm_so)
464 {
465 i2 = i;
466 /* Skip leading and trailing space characters, if present.
467 (the regular expressions include those characters to
468 only get matches limited to whole words). */
469 if (p[rm.rm_so] == ' ') rm.rm_so++;
470 if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--;
471 rm2.rm_so = rm.rm_so;
472 rm2.rm_eo = rm.rm_eo;
473 }
474 }
475
476 if (i2 != RE_NUM) {
477 tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so);
478 metar_f[i2] (tokp, info);
479 g_free (tokp);
480 }
481
482 p += rm2.rm_eo;
483 p += strspn (p, " ");
484 }
485 return TRUE(!(0));
486}
487
488static void
489metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
490{
491 WeatherInfo *info = (WeatherInfo *)data;
492 WeatherLocation *loc;
493 const gchar *p, *endtag;
494 gchar *searchkey, *metar;
495 gboolean success = FALSE(0);
496
497 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (info != ((void*)0)) _g_boolean_var_24 = 1; else _g_boolean_var_24
= 0; _g_boolean_var_24; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
498
499 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)((msg->status_code) >= 200 && (msg->status_code
) < 300)
) {
500 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)((msg->status_code) > 0 && (msg->status_code
) < 100)
)
501 info->network_error = TRUE(!(0));
502 else {
503 /* Translators: %d is an error code, and %s the error string */
504 g_warning (_("Failed to get METAR data: %d %s.\n")(mateweather_gettext ("Failed to get METAR data: %d %s.\n")),
505 msg->status_code, msg->reason_phrase);
506 }
507 request_done (info, FALSE(0));
508 return;
509 }
510
511 loc = info->location;
512
513 searchkey = g_strdup_printf ("<raw_text>%s", loc->code);
514 p = strstr (msg->response_body->data, searchkey);
515 g_free (searchkey);
516 if (p) {
517 p += WEATHER_LOCATION_CODE_LEN4 + 11;
518 endtag = strstr (p, "</raw_text>");
519 if (endtag)
520 metar = g_strndup (p, endtag - p);
521 else
522 metar = g_strdup (p)g_strdup_inline (p);
523 success = metar_parse (metar, info);
524 g_free (metar);
525 } else if (!strstr (msg->response_body->data, "aviationweather.gov")) {
526 /* The response doesn't even seem to have come from NOAA...
527 * most likely it is a wifi hotspot login page. Call that a
528 * network error.
529 */
530 info->network_error = TRUE(!(0));
531 }
532
533 info->valid = success;
534 request_done (info, TRUE(!(0)));
535}
536
537/* Read current conditions and fill in info structure */
538void
539metar_start_open (WeatherInfo *info)
540{
541 WeatherLocation *loc;
542 SoupMessage *msg;
543
544 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (info != ((void*)0)) _g_boolean_var_25 = 1; else _g_boolean_var_25
= 0; _g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
("MateWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
545 info->valid = info->network_error = FALSE(0);
546 loc = info->location;
547 if (loc == NULL((void*)0)) {
548 g_warning (_("WeatherInfo missing location")(mateweather_gettext ("WeatherInfo missing location")));
549 return;
550 }
551
552 msg = soup_form_request_new (
553 "GET", "https://www.aviationweather.gov/adds/dataserver_current/httpparam",
554 "dataSource", "metars",
555 "requestType", "retrieve",
556 "format", "xml",
557 "hoursBeforeNow", "3",
558 "mostRecent", "true",
559 "fields", "raw_text",
560 "stationString", loc->code,
561 NULL((void*)0));
562 soup_session_queue_message (info->session, msg, metar_finish, info);
563
564 info->requests_pending++;
565}
diff --git a/2023-09-01-181303-5846-1@58a183825058_master/scanview.css b/2023-09-01-181303-5846-1@58a183825058_master/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-09-01-181303-5846-1@58a183825058_master/sorttable.js b/2023-09-01-181303-5846-1@58a183825058_master/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-09-01-181303-5846-1@58a183825058_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* location-entry.c - Location-selecting text entry
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+/**
+ * SECTION:location-entry
+ * @Title: MateWeatherLocationEntry
+ *
+ * A subclass of #GtkEntry that provides autocompletion on
+ * #MateWeatherLocation<!-- -->s
+ */
+
+G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+    PROP_0,
+
+    PROP_TOP,
+    PROP_LOCATION,
+
+    LAST_PROP
+};
+
+static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+						 MateWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+enum
+{
+    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION,
+    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+    MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+    MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+			 GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+				GtkTreeModel       *model,
+				GtkTreeIter        *iter,
+				gpointer            entry);
+static void     entry_changed (MateWeatherLocationEntry *entry);
+
+static void
+mateweather_location_entry_init (MateWeatherLocationEntry *entry)
+{
+    GtkEntryCompletion *completion;
+
+    completion = gtk_entry_completion_new ();
+
+    gtk_entry_completion_set_popup_set_width (completion, FALSE);
+    gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+    gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+    g_signal_connect (completion, "match_selected",
+		      G_CALLBACK (match_selected), entry);
+
+    gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+    g_object_unref (completion);
+
+    entry->custom_text = FALSE;
+    g_signal_connect (entry, "changed",
+		      G_CALLBACK (entry_changed), NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+    if (entry->top)
+	mateweather_location_unref (entry->top);
+
+    G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+    object_class->finalize = finalize;
+    object_class->set_property = set_property;
+    object_class->get_property = get_property;
+
+    /* properties */
+    g_object_class_install_property (
+	object_class, PROP_TOP,
+	g_param_spec_pointer ("top",
+			      "Top Location",
+			      "The MateWeatherLocation whose children will be used to fill in the entry",
+			      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (
+	object_class, PROP_LOCATION,
+	g_param_spec_pointer ("location",
+			      "Location",
+			      "The selected MateWeatherLocation",
+			      G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+    switch (prop_id) {
+    case PROP_TOP:
+	mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object),
+					     g_value_get_pointer (value));
+	break;
+    case PROP_LOCATION:
+	mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object),
+					      g_value_get_pointer (value));
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+    MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object);
+
+    switch (prop_id) {
+    case PROP_LOCATION:
+	g_value_set_pointer (value, entry->location);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+entry_changed (MateWeatherLocationEntry *entry)
+{
+    entry->custom_text = TRUE;
+}
+
+static void
+set_location_internal (MateWeatherLocationEntry *entry,
+		       GtkTreeModel          *model,
+		       GtkTreeIter           *iter)
+{
+    MateWeatherLocation *loc;
+    char *name;
+
+    if (entry->location)
+	mateweather_location_unref (entry->location);
+
+    if (iter) {
+	gtk_tree_model_get (model, iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			    -1);
+	entry->location = mateweather_location_ref (loc);
+	gtk_entry_set_text (GTK_ENTRY (entry), name);
+	entry->custom_text = FALSE;
+	g_free (name);
+    } else {
+	entry->location = NULL;
+	gtk_entry_set_text (GTK_ENTRY (entry), "");
+	entry->custom_text = TRUE;
+    }
+
+    gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+    g_object_notify (G_OBJECT (entry), "location");
+}
+
+/**
+ * mateweather_location_entry_set_location:
+ * @entry: a #MateWeatherLocationEntry
+ * @loc: (allow-none): a #MateWeatherLocation in @entry, or %NULL to
+ * clear @entry
+ *
+ * Sets @entry's location to @loc, and updates the text of the
+ * entry accordingly.
+ **/
+void
+mateweather_location_entry_set_location (MateWeatherLocationEntry *entry,
+				      MateWeatherLocation      *loc)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+	if (loc == cmploc) {
+	    set_location_internal (entry, model, &iter);
+	    return;
+	}
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+}
+
+/**
+ * mateweather_location_entry_get_location:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Gets the location that was set by a previous call to
+ * mateweather_location_entry_set_location() or was selected by the user.
+ *
+ * Return value: (transfer full) (allow-none): the selected location
+ * (which you must unref when you are done with it), or %NULL if no
+ * location is selected.
+ **/
+MateWeatherLocation *
+mateweather_location_entry_get_location (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+    if (entry->location)
+	return mateweather_location_ref (entry->location);
+    else
+	return NULL;
+}
+
+/**
+ * mateweather_location_entry_has_custom_text:
+ * @entry: a #MateWeatherLocationEntry
+ *
+ * Checks whether or not @entry's text has been modified by the user.
+ * Note that this does not mean that no location is associated with @entry.
+ * mateweather_location_entry_get_location() should be used for this.
+ *
+ * Return value: %TRUE if @entry's text was modified by the user, or %FALSE if
+ * it's set to the default text of a location.
+ **/
+gboolean
+mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry)
+{
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+
+    return entry->custom_text;
+}
+
+/**
+ * mateweather_location_entry_set_city:
+ * @entry: a #MateWeatherLocationEntry
+ * @city_name: (allow-none): the city name, or %NULL
+ * @code: the METAR station code
+ *
+ * Sets @entry's location to a city with the given @code, and given
+ * @city_name, if non-%NULL. If there is no matching city, sets
+ * @entry's location to %NULL.
+ *
+ * Return value: %TRUE if @entry's location could be set to a matching city,
+ * %FALSE otherwise.
+ **/
+gboolean
+mateweather_location_entry_set_city (MateWeatherLocationEntry *entry,
+				  const char            *city_name,
+				  const char            *code)
+{
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    MateWeatherLocation *cmploc;
+    const char *cmpcode;
+    char *cmpname;
+
+    g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE);
+    g_return_val_if_fail (code != NULL, FALSE);
+
+    completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+    model = gtk_entry_completion_get_model (completion);
+
+    gtk_tree_model_get_iter_first (model, &iter);
+    do {
+	gtk_tree_model_get (model, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+			    -1);
+
+	cmpcode = mateweather_location_get_code (cmploc);
+	if (!cmpcode || strcmp (cmpcode, code) != 0)
+	    continue;
+
+	if (city_name) {
+	    cmpname = mateweather_location_get_city_name (cmploc);
+	    if (!cmpname || strcmp (cmpname, city_name) != 0) {
+		g_free (cmpname);
+		continue;
+	    }
+	    g_free (cmpname);
+	}
+
+	set_location_internal (entry, model, &iter);
+	return TRUE;
+    } while (gtk_tree_model_iter_next (model, &iter));
+
+    set_location_internal (entry, model, NULL);
+
+    return FALSE;
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc,
+			   const char *parent_display_name,
+			   const char *parent_compare_name)
+{
+    MateWeatherLocation **children;
+    char *display_name, *compare_name;
+    GtkTreeIter iter;
+    int i;
+
+    children = mateweather_location_get_children (loc);
+
+    switch (mateweather_location_get_level (loc)) {
+    case MATEWEATHER_LOCATION_WORLD:
+    case MATEWEATHER_LOCATION_REGION:
+    case MATEWEATHER_LOCATION_ADM2:
+	/* Ignore these levels of hierarchy; just recurse, passing on
+	 * the names from the parent node.
+	 */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       parent_display_name,
+				       parent_compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_COUNTRY:
+	/* Recurse, initializing the names to the country name */
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       mateweather_location_get_name (loc),
+				       mateweather_location_get_sort_name (loc));
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_ADM1:
+	/* Recurse, adding the ADM1 name to the country name */
+	display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name);
+
+	for (i = 0; children[i]; i++) {
+	    fill_location_entry_model (store, children[i],
+				       display_name, compare_name);
+	}
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+
+    case MATEWEATHER_LOCATION_CITY:
+	if (children[0] && children[1]) {
+	    /* If there are multiple (<location>) children, add a line
+	     * for each of them.
+	     */
+	    for (i = 0; children[i]; i++) {
+		display_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_name (loc),
+						mateweather_location_get_name (children[i]),
+						parent_display_name);
+		compare_name = g_strdup_printf ("%s (%s), %s",
+						mateweather_location_get_sort_name (loc),
+						mateweather_location_get_sort_name (children[i]),
+						parent_compare_name);
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+				    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				    -1);
+
+		g_free (display_name);
+		g_free (compare_name);
+	    }
+	} else if (children[0]) {
+	    /* Else there's only one location. This is a mix of the
+	     * city-with-multiple-location case above and the
+	     * location-with-no-city case below.
+	     */
+	    display_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_name (loc),
+					    parent_display_name);
+	    compare_name = g_strdup_printf ("%s, %s",
+					    mateweather_location_get_sort_name (loc),
+					    parent_compare_name);
+
+	    gtk_tree_store_append (store, &iter, NULL);
+	    gtk_tree_store_set (store, &iter,
+				MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0],
+				MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+				MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+				-1);
+
+	    g_free (display_name);
+	    g_free (compare_name);
+	}
+	break;
+
+    case MATEWEATHER_LOCATION_WEATHER_STATION:
+	/* <location> with no parent <city>, or <city> with a single
+	 * child <location>.
+	 */
+	display_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_name (loc),
+					parent_display_name);
+	compare_name = g_strdup_printf ("%s, %s",
+					mateweather_location_get_sort_name (loc),
+					parent_compare_name);
+
+	gtk_tree_store_append (store, &iter, NULL);
+	gtk_tree_store_set (store, &iter,
+			    MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+			    MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+			    MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+			    -1);
+
+	g_free (display_name);
+	g_free (compare_name);
+	break;
+    }
+
+    mateweather_location_free_children (loc, children);
+}
+
+static void
+mateweather_location_entry_build_model (MateWeatherLocationEntry *entry,
+				     MateWeatherLocation *top)
+{
+    GtkTreeStore *store = NULL;
+
+    g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry));
+    entry->top = mateweather_location_ref (top);
+
+    store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+    fill_location_entry_model (store, top, NULL, NULL);
+    gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+				    GTK_TREE_MODEL (store));
+    g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+	   gboolean whole_word, gboolean is_first_word)
+{
+    char *p = (char *)full_name - 1;
+
+    while ((p = strchr (p + 1, *word))) {
+	if (strncmp (p, word, word_len) != 0)
+	    continue;
+
+	if (p > (char *)full_name) {
+	    char *prev = g_utf8_prev_char (p);
+
+	    /* Make sure p points to the start of a word */
+	    if (g_unichar_isalpha (g_utf8_get_char (prev)))
+		continue;
+
+	    /* If we're matching the first word of the key, it has to
+	     * match the first word of the location, city, state, or
+	     * country. Eg, it either matches the start of the string
+	     * (which we already know it doesn't at this point) or
+	     * it is preceded by the string ", " (which isn't actually
+	     * a perfect test. FIXME)
+	     */
+	    if (is_first_word) {
+		if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+		    continue;
+	    }
+	}
+
+	if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+	    continue;
+
+	return p;
+    }
+    return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+	 GtkTreeIter *iter, gpointer user_data)
+{
+    char *name, *name_mem;
+    MateWeatherLocation *loc;
+    gboolean is_first_word = TRUE, match;
+    int len;
+
+    gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+			MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+			MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+			-1);
+    name = name_mem;
+
+    if (!loc) {
+	g_free (name_mem);
+	return FALSE;
+    }
+
+    /* All but the last word in KEY must match a full word from NAME,
+     * in order (but possibly skipping some words from NAME).
+     */
+    len = strcspn (key, " ");
+    while (key[len]) {
+	name = find_word (name, key, len, TRUE, is_first_word);
+	if (!name) {
+	    g_free (name_mem);
+	    return FALSE;
+	}
+
+	key += len;
+	while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+	    key = g_utf8_next_char (key);
+	while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+	    name = g_utf8_next_char (name);
+
+	len = strcspn (key, " ");
+	is_first_word = FALSE;
+    }
+
+    /* The last word in KEY must match a prefix of a following word in NAME */
+    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+    g_free (name_mem);
+    return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+		GtkTreeModel       *model,
+		GtkTreeIter        *iter,
+		gpointer            entry)
+{
+    set_location_internal (entry, model, iter);
+    return TRUE;
+}
+
+/**
+ * mateweather_location_entry_new:
+ * @top: the top-level location for the entry.
+ *
+ * Creates a new #MateWeatherLocationEntry.
+ *
+ * @top will normally be a location returned from
+ * mateweather_location_new_world(), but you can create an entry that
+ * only accepts a smaller set of locations if you want.
+ *
+ * Return value: the new #MateWeatherLocationEntry
+ **/
+GtkWidget *
+mateweather_location_entry_new (MateWeatherLocation *top)
+{
+    return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY,
+			 "top", top,
+			 NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-09-01-181404-7605-cppcheck@58a183825058_master/1.html b/2023-09-01-181404-7605-cppcheck@58a183825058_master/1.html new file mode 100644 index 00000000..95970ba7 --- /dev/null +++ b/2023-09-01-181404-7605-cppcheck@58a183825058_master/1.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* weather-priv.h - Private header for weather server functions.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEATHER_PRIV_H_
+#define __WEATHER_PRIV_H_
+
+#include "config.h"
+
+#include <time.h>
+#include <libintl.h>
+#include <math.h>
+#include <libsoup/soup.h>
+
+#include "weather.h"
+#include "mateweather-location.h"
+
+const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1);<--- There is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2);
+#define _(str) (mateweather_gettext (str))
+#define C_(context, str) (mateweather_dpgettext (context, str))
+#define N_(str) (str)
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc,
+							const char *name);
+
+/*
+ * Weather information.
+ */
+
+struct _WeatherConditions {
+    gboolean significant;
+    WeatherConditionPhenomenon phenomenon;
+    WeatherConditionQualifier qualifier;
+};
+
+typedef struct _WeatherConditions WeatherConditions;
+
+typedef gdouble WeatherTemperature;
+typedef gdouble WeatherHumidity;
+typedef gdouble WeatherWindSpeed;
+typedef gdouble WeatherPressure;
+typedef gdouble WeatherVisibility;
+typedef time_t WeatherUpdate;
+
+struct _WeatherInfo {
+    WeatherForecastType forecast_type;
+
+    TempUnit temperature_unit;
+    SpeedUnit speed_unit;
+    PressureUnit pressure_unit;
+    DistanceUnit distance_unit;
+
+    gboolean valid;
+    gboolean network_error;
+    gboolean sunriseValid;
+    gboolean sunsetValid;
+    gboolean midnightSun;
+    gboolean polarNight;
+    gboolean moonValid;
+    gboolean tempMinMaxValid;
+    WeatherLocation *location;
+    WeatherUpdate update;
+    WeatherSky sky;
+    WeatherConditions cond;
+    WeatherTemperature temp;
+    WeatherTemperature temp_min;
+    WeatherTemperature temp_max;
+    WeatherTemperature dew;
+    WeatherWindDirection wind;
+    WeatherWindSpeed windspeed;
+    WeatherPressure pressure;
+    WeatherVisibility visibility;
+    WeatherUpdate sunrise;
+    WeatherUpdate sunset;
+    WeatherMoonPhase moonphase;
+    WeatherMoonLatitude moonlatitude;
+    gchar *forecast;
+    GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
+    gchar *radar_buffer;
+    gchar *radar_url;
+    GdkPixbufLoader *radar_loader;
+    GdkPixbufAnimation *radar;
+    SoupSession *session;
+    gint requests_pending;
+
+    WeatherInfoFunc finish_cb;
+    gpointer cb_data;
+};
+
+/*
+ * Enum -> string conversions.
+ */
+
+const gchar *	weather_wind_direction_string	(WeatherWindDirection wind);
+const gchar *	weather_sky_string		(WeatherSky sky);
+const gchar *	weather_conditions_string	(WeatherConditions cond);
+
+/* Values common to the parsing source files */
+
+#define DATA_SIZE			5000
+
+#define CONST_DIGITS			"0123456789"
+#define CONST_ALPHABET			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* Units conversions and names */
+
+#define TEMP_F_TO_C(f)			(((f) - 32.0) * (5.0/9.0))
+#define TEMP_F_TO_K(f)			((f + 459.67) * (5.0/9.0))
+#define TEMP_C_TO_F(c)			(((c) * (9.0/5.0)) + 32.0)
+
+#define WINDSPEED_KNOTS_TO_KPH(knots)	((knots) * 1.851965)
+#define WINDSPEED_KNOTS_TO_MPH(knots)	((knots) * 1.150779)
+#define WINDSPEED_KNOTS_TO_MS(knots)	((knots) * 0.514444)
+#define WINDSPEED_MS_TO_KNOTS(ms)	((ms) / 0.514444)
+/* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */
+#define WINDSPEED_KNOTS_TO_BFT(knots)	(pow ((knots) * 0.615363, 0.666666))
+
+#define PRESSURE_INCH_TO_KPA(inch)	((inch) * 3.386)
+#define PRESSURE_INCH_TO_HPA(inch)	((inch) * 33.86)
+#define PRESSURE_INCH_TO_MM(inch)	((inch) * 25.40005)
+#define PRESSURE_INCH_TO_MB(inch)	(PRESSURE_INCH_TO_HPA (inch))
+#define PRESSURE_INCH_TO_ATM(inch)	((inch) * 0.033421052)
+#define PRESSURE_MBAR_TO_INCH(mbar)	((mbar) * 0.029533373)
+
+#define VISIBILITY_SM_TO_KM(sm)		((sm) * 1.609344)
+#define VISIBILITY_SM_TO_M(sm)		(VISIBILITY_SM_TO_KM (sm) * 1000)
+
+#define DEGREES_TO_RADIANS(deg)		((fmod ((deg),360.) / 180.) * M_PI)
+#define RADIANS_TO_DEGREES(rad)		((rad) * 180. / M_PI)
+#define RADIANS_TO_HOURS(rad)		((rad) * 12. / M_PI)
+
+/*
+ * Planetary Mean Orbit and their progressions from J2000 are based on the
+ * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
+ * converting longitudes from heliocentric to geocentric coordinates (+180)
+ */
+#define EPOCH_TO_J2000(t)          ((gdouble)(t)-946727935.816)
+#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981)
+#define SOL_PROGRESSION            (360./365.242191)
+#define PERIGEE_LONGITUDE(d)       (282.93768193 + (d)/36525.*0.32327364)
+
+void		metar_start_open	(WeatherInfo *info);
+void		iwin_start_open		(WeatherInfo *info);
+void		metoffice_start_open	(WeatherInfo *info);
+void		bom_start_open		(WeatherInfo *info);
+void		wx_start_open		(WeatherInfo *info);
+
+gboolean	metar_parse		(gchar *metar,
+					 WeatherInfo *info);
+
+gboolean	requests_init		(WeatherInfo *info);
+void		request_done		(WeatherInfo *info,
+					 gboolean     ok);
+
+void		ecl2equ			(gdouble t,
+					 gdouble eclipLon,
+					 gdouble eclipLat,
+					 gdouble *ra,
+					 gdouble *decl);
+gdouble		sunEclipLongitude	(time_t t);
+gboolean	calc_sun		(WeatherInfo *info);
+gboolean	calc_sun_time		(WeatherInfo *info, time_t t);
+gboolean	calc_moon		(WeatherInfo *info);
+gboolean	calc_moon_phases	(WeatherInfo *info, time_t *phases);
+
+void		free_forecast_list	(WeatherInfo *info);
+
+#endif /* __WEATHER_PRIV_H_ */
+
+
+ +
+ +
+ + diff --git a/2023-09-01-181404-7605-cppcheck@58a183825058_master/index.html b/2023-09-01-181404-7605-cppcheck@58a183825058_master/index.html new file mode 100644 index 00000000..3272a42b --- /dev/null +++ b/2023-09-01-181404-7605-cppcheck@58a183825058_master/index.html @@ -0,0 +1,201 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
libmateweather/location-entry.c
303variableScope398styleThe scope of the variable 'cmpcode' can be reduced.
libmateweather/weather-priv.h
32unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If mateweather_gettext is a macro then please configure it.
+
+ +
+ + diff --git a/2023-09-01-181404-7605-cppcheck@58a183825058_master/stats.html b/2023-09-01-181404-7605-cppcheck@58a183825058_master/stats.html new file mode 100644 index 00000000..4a1202b9 --- /dev/null +++ b/2023-09-01-181404-7605-cppcheck@58a183825058_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - libmateweather + + + + + +
+ + + +
+

Top 10 files for error severity, total findings: 1
+   1  libmateweather/weather-priv.h
+

+

Top 10 files for style severity, total findings: 1
+   1  libmateweather/location-entry.c
+

+ +
+ +
+ + diff --git a/2023-09-01-181404-7605-cppcheck@58a183825058_master/style.css b/2023-09-01-181404-7605-cppcheck@58a183825058_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-09-01-181404-7605-cppcheck@58a183825058_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..18ed0fcf --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +libmateweather.mate-desktop.dev diff --git a/index.html b/index.html new file mode 100644 index 00000000..868ecd39 --- /dev/null +++ b/index.html @@ -0,0 +1,46 @@ + + + + + libmateweather Code Analyzer results + + +

+ mate-desktop/libmateweather Static analyzer results +

+ GitHub + Build Status +
+Commit: 58a1838250583dda0775bd4dea7712071e229c16
+Compare: e4cb5aac0a7c...58a183825058
+Branch: master
+Time: 2023-09-01 18:14:04+00:00
+Messages:
+
+tx: cleanup configs
+
+
+ + +