├── .github └── workflows │ ├── linux-ci.yml │ └── windows-ci.yml ├── .gitignore ├── CMakeLists.txt ├── HISTORY ├── LICENSE ├── Makefile ├── README.MDSP ├── README.md ├── include └── metar.h └── src ├── antoi.c ├── charcmp.c ├── decode_metar.c ├── decode_metar_remark.c ├── fracpart.c ├── local.h ├── metar_structs.h ├── metar_test.c ├── print_decoded_metar.c ├── stspack2.c └── stspack3.c /.github/workflows/linux-ci.yml: -------------------------------------------------------------------------------- 1 | name: Linux CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: make 17 | run: make 18 | - name: make test 19 | run: make test 20 | -------------------------------------------------------------------------------- /.github/workflows/windows-ci.yml: -------------------------------------------------------------------------------- 1 | name: Windows CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | # Path to the solution file relative to the root of the project. 11 | SOLUTION_FILE_PATH: . 12 | 13 | # Configuration type to build. 14 | # You can convert this to a build matrix if you need coverage of multiple configuration types. 15 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 16 | BUILD_CONFIGURATION: Release 17 | 18 | jobs: 19 | build: 20 | runs-on: windows-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | 25 | - name: Configure 26 | run: mkdir build && cd build && cmake .. 27 | 28 | - name: Build 29 | run: cmake --build build --config ${{env.BUILD_CONFIGURATION}} -- /property:Prefer32bit=false /p:Platform=x64 30 | 31 | - name: Test 32 | run: build\${{env.BUILD_CONFIGURATION}}\metar_test.exe 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | src/*.o 3 | metar_test 4 | metar_test.exe 5 | build/ 6 | .vscode/ 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1...3.15) 2 | 3 | project(mdsplib LANGUAGES C) 4 | 5 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 6 | set(CMAKE_BUILD_TYPE "Release" CACHE 7 | STRING "Choose the type of build." FORCE) 8 | endif() 9 | 10 | IF (MSVC) 11 | # MSVC is logs many inline warnings 12 | add_definitions("/wd4710") 13 | add_definitions("/wd4711") 14 | add_definitions("/wd4068") 15 | add_definitions("/wd4109") 16 | ENDIF() 17 | 18 | list(APPEND SRCS src/antoi.c) 19 | list(APPEND SRCS src/charcmp.c) 20 | list(APPEND SRCS src/decode_metar.c) 21 | list(APPEND SRCS src/decode_metar_remark.c) 22 | list(APPEND SRCS src/fracpart.c) 23 | list(APPEND SRCS src/local.h) 24 | list(APPEND SRCS src/metar_structs.h) 25 | list(APPEND SRCS src/print_decoded_metar.c) 26 | list(APPEND SRCS src/stspack2.c) 27 | list(APPEND SRCS src/stspack3.c) 28 | 29 | add_library(metar STATIC ${SRCS}) 30 | 31 | add_executable(metar_test src/metar_test.c) 32 | 33 | target_link_libraries(metar_test PRIVATE metar) 34 | -------------------------------------------------------------------------------- /HISTORY: -------------------------------------------------------------------------------- 1 | Version History of the MDSP Library 2 | 3 | December 10, 2003 - Ver. 0.11 4 | ----------------------------------- 5 | Added "dmetar" and "libmetar.a" to 'make clean'. 6 | 7 | Added the LGPL notice to all source files and added "LICENSE". 8 | 9 | Added up-to-date contact information to "README". 10 | 11 | 12 | October 19, 2001 - Ver. 0.11 13 | ----------------------------------- 14 | Added 'make install'. It copies metar.h to /usr/local/include and copies 15 | libmetar.a to /usr/local/lib. Also chmods them to 0664. 16 | 17 | Changed the "bool" typdef to "MDSP_BOOL" to avoid problems with C++ and 18 | Objective C. 19 | 20 | Added function sprint_metar. It's just prtDMTAR(), but made so that it 21 | prints to a string. I changed prtDMTAR() so that it calls 22 | sprint_metar(). 23 | 24 | Added function dcdNetMETAR. It decodes the METARs that the NWS provides 25 | on their servers. 26 | 27 | Fixed bug with printing METARs, where it would print the charVertVsby 28 | field of decoded_METAR. This field is never set, and never used. Just 29 | commented out the code that prints it in prtdmetr.c. 30 | 31 | 32 | July 6, 2001 - Ver. 0.1 33 | ----------------------------------- 34 | First release, based on the METAR Decoder Software Package version 1.8. 35 | 36 | Made it compile and function properly with gcc. 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # $Id$ 2 | 3 | CC = gcc 4 | #CC = clang 5 | 6 | #CFLAGS = -g -O2 -fPIC -DDEBUGZZ 7 | #CFLAGS = -g -O0 -fPIC -DDEBUGZZ 8 | #CFLAGS = -g -Os -fPIC 9 | CFLAGS = -g -O2 -fPIC 10 | #CFLAGS = -g -O0 -fPIC 11 | 12 | LIBS = 13 | 14 | library: libmetar.a 15 | 16 | all: metar_test library 17 | 18 | libmetar.a: src/antoi.o src/charcmp.o src/decode_metar.o src/decode_metar_remark.o src/fracpart.o src/print_decoded_metar.o src/stspack2.o src/stspack3.o 19 | ar ruv libmetar.a src/antoi.o src/charcmp.o src/decode_metar.o src/decode_metar_remark.o src/fracpart.o src/print_decoded_metar.o src/stspack2.o src/stspack3.o 20 | ranlib libmetar.a 21 | 22 | metar_test: src/metar_test.o libmetar.a 23 | $(CC) $(CFLAGS) -o metar_test src/metar_test.o libmetar.a $(LIBS) 24 | 25 | src/antoi.o: src/antoi.c src/local.h 26 | $(CC) $(CFLAGS) -c src/antoi.c -o src/antoi.o 27 | 28 | src/charcmp.o: src/charcmp.c src/local.h 29 | $(CC) $(CFLAGS) -c src/charcmp.c -o src/charcmp.o 30 | 31 | src/decode_metar.o: src/decode_metar.c src/metar_structs.h 32 | $(CC) $(CFLAGS) -c src/decode_metar.c -o src/decode_metar.o 33 | 34 | src/decode_metar_remark.o: src/decode_metar_remark.c src/metar_structs.h 35 | $(CC) $(CFLAGS) -c src/decode_metar_remark.c -o src/decode_metar_remark.o 36 | 37 | src/metar_test.o: src/metar_test.c src/metar_structs.h 38 | $(CC) $(CFLAGS) -c src/metar_test.c -o src/metar_test.o 39 | 40 | src/fracpart.o: src/fracpart.c src/local.h 41 | $(CC) $(CFLAGS) -c src/fracpart.c -o src/fracpart.o 42 | 43 | src/print_decoded_metar.o: src/print_decoded_metar.c src/metar_structs.h 44 | $(CC) $(CFLAGS) -c src/print_decoded_metar.c -o src/print_decoded_metar.o 45 | 46 | src/stspack2.o: src/stspack2.c src/local.h 47 | $(CC) $(CFLAGS) -c src/stspack2.c -o src/stspack2.o 48 | 49 | src/stspack3.o: src/stspack3.c src/local.h 50 | $(CC) $(CFLAGS) -c src/stspack3.c -o src/stspack3.o 51 | 52 | clean: 53 | rm -f src/*.o metar_test libmetar.a 54 | 55 | install: library 56 | cp include/metar.h /usr/local/include/ 57 | chmod 0644 /usr/local/include/metar.h 58 | cp libmetar.a /usr/local/lib/ 59 | chmod 0644 /usr/local/lib/libmetar.a 60 | ranlib /usr/local/lib/libmetar.a 61 | 62 | test: metar_test 63 | ./metar_test 64 | 65 | .PHONY : clean 66 | clean: 67 | ifeq ($(OS), Windows_NT) 68 | echo off 69 | del /q src\*.o 70 | del /q metar_test.exe 71 | del /q libmetar.a 72 | echo on 73 | else 74 | rm -f libmetar.a src/*.o src/*.a metar_test 75 | endif 76 | -------------------------------------------------------------------------------- /README.MDSP: -------------------------------------------------------------------------------- 1 | METAR DECODER SOFTWARE PACKAGE (MDSP) 2 | 3 | Update History: 4 | 5 | NEW 6 | 7 | 29 June 1998 (Posting of METAR Decoder, 8 | Upgrade,Version 1.8) 9 | 10 | 15 July 1996 (Posting of METAR Decoder, 11 | Upgrade,Version 1.7) 12 | 13 | 1) METAR date/time groups that are not 14 | postfixed with 'Z' will be 15 | recognized and decoded along with 16 | date/time groups that are correctly 17 | encoded. 18 | 2) Station identifiers that include a 19 | mix of alphanumeric characters 20 | following the first alpha character 21 | will be accepted as a valid station 22 | ID. 23 | 3) Incorrectly coded prevailing 24 | visibility groups (e.g. 1/SM) will 25 | be ignored as spurious or 26 | extraneous groups. 27 | 4) Indeterminant 3/6-HR precipitation 28 | groups (i.e. 6////) are flagged 29 | using a boolean variable. The 30 | boolean variable is TRUE, if 6//// 31 | appears in the observation 32 | or FALSE, if 6//// does not appear 33 | in the observation. 34 | 5) The keyword 'COR', a positionally 35 | dependent METAR group, will be 36 | recognized and decoded whether it 37 | appears before or after the 38 | date/time group. 39 | 6) Spurious or extraneous groups that 40 | occur within the body of a METAR 41 | observation will be skipped without 42 | compromising the positional 43 | integrity of groups that may 44 | follow. 45 | 7) Code has been added to the 46 | DCDMETAR.C and DCDMTRMK.C files 47 | to protect against attempts at 48 | using NULL pointers in string 49 | functions. 50 | 51 | 52 | 26 June 1996 (Posting of METAR Decoder, 53 | Upgrade,Version 1.6) 54 | 21 May 1996 (Posting of METAR Decoder, 55 | Upgrade,Version 1.5) 56 | 15 May 1996 (Posting of METAR Decoder, 57 | Upgrade,Version 1.4) 58 | 07 May 1996 (Posting of METAR Decoder, 59 | Upgrade,Version 1.3) 60 | 26 February 1996 (Posting of METAR Decoder, 61 | Upgrade,Version 1.2) 62 | 20 December 1995 (Posting of METAR Decoder, 63 | Upgrade,Version 1.1) 64 | 11 June 1995 (Posting of METAR Decoder, 65 | Version 1.0) 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 | General Information: 95 | -------------------- 96 | 97 | The Systems Operations Center (SOC) of the National Weather 98 | Service (NWS) has developed a "C" language software package 99 | to decode WMO FM 15-IX Ext. (METAR) and FM 16-IX Ext. (SPECI) 100 | formatted reports. The format specifications for these report 101 | types are described in the Federal Meteorological Handbook Number 102 | 1 (FMH-1), Surface Weather Observations and Reports (December 103 | 1995). 104 | 105 | A METAR report may consist of two parts - 106 | 107 | 1) the main body of the report consists of observational 108 | data that meets aviation requirements (e.g. wind speed 109 | and direction, sky condition, temperature and dew 110 | point temperature, etc.) 111 | 112 | 2) the remarks section may consist of one or more sections 113 | (i.e. Automated and Manual, Plain Language (Manual 114 | Only), and Additive Data and Automated Maintenance) 115 | 116 | The MDSP is specifically designed to meet SOC operational 117 | requirements. Nevertheless, it is a comprehensive decoder. As a 118 | result, SOC management decided to make the MDSP available to any 119 | interested party via the Internet. However, as the SOC makes this 120 | software available, it neither implies or guarantees the accuracy 121 | or dependability of the MDSP. 122 | 123 | The MDSP makes no attempt to decode any METAR/SPECI group 124 | that does not conform to the METAR/SPECI format outlined in FMH-1 125 | (METAR). 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | How Do You Use It?: 140 | ------------------- 141 | 142 | The METAR Decoder (DCDMETAR) is a "C" language routine that 143 | takes two arguments. The 1st argument is a pointer to a METAR 144 | report character string. The 2nd argument is a pointer to a 145 | Decoded_METAR data type (defined in METAR.H). DCDMETAR returns 146 | 12, if it encounters an invalid station ID (i.e. a station that 147 | does not contains 4 characters statino ID and/or whose first 148 | character is not alpha). Otherwise, it returns 0. 149 | 150 | All decoded groups/elements are assigned to members of the 151 | structure whose address is that of the 2nd input argument. If 152 | the decoder encounters a multiple instance of the same 153 | group/element in the Remarks section of the Decoder, then that 154 | group/element is not decoded. 155 | 156 | The input METAR report must be a character string that is 157 | terminated by a sentinel (i.e. '\0'). The report string should 158 | also be free of any communication transmission characters (e.g. 159 | carriage returns, linefeeds, etc.). Each group in the report 160 | must be separated by at least one blank character. 161 | 162 | The decoded groups/elements of the METAR report are 163 | evaluated as one of 4 basic data types - int, bool, char, or 164 | float. All decoded METAR structure members are initialized prior 165 | to decoding each input METAR report. All int variables are set 166 | to MAXINT ( defined in LOCAL.H). All bool variables are set to 167 | FALSE (i.e. 0). All char and char strings are set to '\0'(s). 168 | All float variables are set to (float) MAXINT. 169 | 170 | METAR decoded structure members retain their initialization 171 | values, if no groups/elements were decoded from the METAR report 172 | and assigned to those members. 173 | 174 | The METAR Decoder has the following function prototype: 175 | 176 | 177 | int decode_metar( char *observation, Decoded_METAR *Mptr ), 178 | 179 | The following program segment illustrates how the decode_metar 180 | function might be invoked: 181 | 182 | 183 | 184 | 185 | #include 186 | main() 187 | { 188 | /***************************/ 189 | /* DECLARE LOCAL VARIABLES */ 190 | /***************************/ 191 | 192 | Decoded_METAR MetarStruct, 193 | *Mptr = &MetarStruct; 194 | char *observation; 195 | . 196 | . 197 | . 198 | if ( (observation = getMETAR( selectionParms )) 199 | 200 | != NULL ) { 201 | if( decode_metar( observation, Mptr) != 0 ) 202 | 203 | printf("Error Msg\m"); 204 | 205 | else { 206 | 'Process decoded METAR 207 | 208 | groups/elements' 209 | } 210 | } 211 | . 212 | . 213 | . 214 | 215 | 216 | Within the routine that calls decode_metar, a variable must be 217 | declared as a Decoded_METAR type. The address of that 218 | Decoded_METAR variable and a pointer to a METAR report string are 219 | then passed to the decode_metar routine. The function getMETAR is 220 | for illustrative purposes only and simply represents a generic routine that the user must furnish in 221 | order to supply METAR reports to the decode_metar routine. 222 | 223 | All of the files listed below have been packaged as a single 224 | self-extracting file called DCDMETAR.EXE. An ASCII version of 225 | these files is also available in the file DCDMETAR.SRC. Each of 226 | the header files and functions in DCDMETAR.SRC are separated by 227 | the delimiter @@ and the name of the file (e.g. @@DRVMETAR.C 228 | would be followed by the DRVMETAR.C source code. 229 | 230 | 1) DRVMETAR.C 6) STSPACK2.C 11) LOCAL.H 231 | 2) DCDMETAR.C 7) STSPACK3.C 232 | 3) DCDMTRMK.C 8) ANTOI.C 233 | 4) PRTDMETR.C 9) CHARCMP.C 234 | 5) FRACPART.C 10) METAR.H 235 | 236 | 237 | 238 | What's Included?: 239 | ----------------- 240 | 241 | The files that make up the MDSP are described below. These 242 | files have been packaged as a single self-extracting file called 243 | DCDMETAR.EXE. If your system can not expand this file, then 244 | you will have to manually extract the individual source and 245 | header files from the file called DCDMETAR.SRC. Each source or 246 | header file within DCDMETAR.SRC is delimited by the 2 characters 247 | "@@" followed by the name of the file (e.g. @@DRVMETAR.C or 248 | @@METAR.H). 249 | 250 | 1) DRVMETAR.C - A main program that acts as a driver for 251 | the MDSP. In its current configuration, DRVMETAR 252 | uses an array of pointers to METAR report character 253 | strings for input to the METAR Decoder. The user may 254 | elect to continue with this configuration and provide 255 | his or her own METAR reports for testing or instead read 256 | individual METAR reports in from a file or some other 257 | database. The METAR report strings that are in DRVMETAR 258 | are not meant to be reports that reflect physical 259 | reality, but rather reports that were designed to 260 | exercise various parts of the MDSP. 261 | 262 | 2) DCDMETAR.C - A function that decodes the main body of 263 | the METAR report. The decoded groups/elements of the 264 | METAR report are stored in a structure of the type 265 | Decoded_METAR. 266 | 267 | 3) DCDMTRMK.C - A function that decodes the remarks section 268 | of the METAR report. The decoded groups/elements of the 269 | METAR report are also stored in a struture of the type 270 | Decoded_METAR. 271 | 272 | 4) PRTDMETR.C - A function that prints the decoded METAR 273 | report groups/elements. 274 | 275 | 5) FRACPART.C - A function that converts a character string 276 | fraction (e.g. "1/4", "1/8", etc.) into a floating point 277 | number. 278 | 279 | 6) STSPACK2.C - A collection of routines written at the 280 | SOC to perform string evaluations that expand upon the 281 | standard C string functions. 282 | 283 | 6) STSPACK3.C - A collection of routines written at the 284 | SOC to perform string evaluations that expand upon the 285 | standard C string functions. 286 | 287 | 7) ANTOI.C - A routine developed at the SOC to convert 288 | variable length numeric character strings into integers. 289 | 290 | 8) CHARCMP.C - A routine developed at the SOC to recognize 291 | character patterns. If a given string pattern is found 292 | in a given character string, CHARCMP returns TRUE. 293 | 294 | Otherwise, it returns FALSE. 295 | 296 | 9) METAR.H - An MDSP header file. This header file 297 | contains the definition of the decoded METAR structure 298 | members. 299 | 300 | 10) LOCAL.H - A "general purpose" header file developed 301 | at the SOC. LOCAL.H is referenced in METAR.H. LOCAL.H 302 | includes a number of locally defined variables that are 303 | used in the MDSP. 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | Printing The METAR Report and/or Decoded METAR Report: 322 | ------------------------------------------------------ 323 | 324 | The routine PRTDMETR may be used to print the decoded 325 | METAR report. PRTDMETR prints the decoded groups/elements in the 326 | order in which they would appear according to the format 327 | described in FMH-1 (METAR). The DRVMETAR module contains a print 328 | statement to print the input METAR report and it also calls the 329 | PRTDMETR routine that prints the decoded METAR data. 330 | 331 | 332 | MDSP Updates: 333 | ------------- 334 | 335 | All updates to the MDSP are based upon: 336 | 337 | 1) meeting all METAR decoding specifications by July 338 | 1, 1996 339 | 340 | 2) responding to decoding problems or errors 341 | that have been demonstrated to exist in the 342 | MDSP 343 | 344 | Areas of on-going MDSP refinement and documentation: 345 | 346 | 1) internal/external documentation 347 | 348 | 349 | 350 | Inquires: 351 | --------- 352 | 353 | Questions, comments, or problems regarding the MDSP, 354 | should be directed to Carl McCalla at - 355 | 356 | NOAA/National Weather Service 357 | 1325 East-West Highway 358 | SSMC2, W/OSO242, Station 5114 359 | Silver Spring, Maryland 20910 360 | 361 | Work: (301) 713-0882, Ext 115 362 | 363 | FAX: (301) 608-0911 364 | 365 | E-Mail Address: Carl.Mccalla@noaa.gov 366 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Linux CI](https://github.com/flightaware/mdsplib/workflows/Linux%20CI/badge.svg) 2 | ![Windows CI](https://github.com/flightaware/mdsplib/workflows/Windows%20CI/badge.svg) 3 | 4 | METAR Decoder Software Package Library 5 | === 6 | 7 | METAR is a format for reporting weather information that is commonly used in aviation worldwide. 8 | 9 | mdsplib parses metars into a data structure that breaks out different weather conditions such as winds, clouds, visibility, temperature, and dew point. Many weather conditions are included such as rain, snow, lightning, smoke, haze, fog, hail and thunderstorms. 10 | 11 | ### ABOUT THE MDSP LIBRARY 12 | 13 | The MDSP Library provides a programmer with two functions, the major one being decode_metar, which decodes a METAR into C structures provided by the library. Also print_decoded_metar, which prints out a decoded METAR structure. 14 | 15 | The MDSP was written by Carl McCalla and released to the public by the US National Weather Service. The MDSP Library is the original MDSP modified to compile and run on *NIX systems. 16 | 17 | Please read the file README.MDSP included in this package. It's the README that comes with the original MDSP from the NWS. You must read the LICENSE before using this program (it's the LGPL). 18 | 19 | ### COMPILING 20 | 21 | Switch into the mdsplib directory and run "make". If you also want the test program to be produced, run "make metar_test" instead. Both commands will produce "metar.a". This is the library. The header file for this library is "metar.h". The test application will be named "dmetar", it takes no parameters. 22 | 23 | "make install" will install the include file to /usr/local/include and the library to /usr/local/lib by default. There is no modern autoconf or cmake-style build architecture so you are limited to editing the source by hand to get it to build on odd operating systems and/or architectures. This isn't super likely or won't take much, though, as it is pretty much sstraight C and doesn't delve into the operating system very much. 24 | 25 | ### USING 26 | 27 | After installing the header file "metar.h" and the library "metar.a", include and use the functions and structures as defined in that file. 28 | 29 | ### FLIGHTAWARE 30 | 31 | FlightAware has made a number of fairly important bug fixes to mdsplib over the years. Also we've smoothed things out, expanded function names past fifteen characters and you know, stuff like that to improve readability. 32 | 33 | As the sourceforge project that's reported to be mdsplib's home seems pretty inactive and isn't configured to receive bug reports or patches, and as we're using git internally, it was ever so easy to put this repo on github. 34 | 35 | As of September 2014 mdsplib can ingest more than 350,000,000 METARs issued between 2008 and 2014 without crashing. The same can not be said for unpatched mdsplib. 36 | 37 | ### SECURITY 38 | 39 | mdsplib was written in the early 90s and is not up to date with current security practices for C coding. Specifically it generally assumes that target strings are large enough to contain whatever is being assembled into them. 40 | 41 | ### PARSING FAILURES 42 | 43 | mdsplib has other problems like because of how it parses and how it is structured in many cases if there is more than one report of something in the remarks, all the remarks pertaining to that thing will be thrown away. That's not good and it's not going to be easy to change it. We're thinking about what to do about it. 44 | 45 | ### ORIGINAL CONTACT 46 | 47 | If you find any bugs/errors or otherwise have questions about the MDSP Library let me know. I'd also welcome any changes and additions to the code. 48 | 49 | Eric McCarthy 50 | 51 | 52 | -------------------------------------------------------------------------------- /include/metar.h: -------------------------------------------------------------------------------- 1 | #ifndef MDSPLIB_METAR_H__ 2 | #define MDSPLIB_METAR_H__ 3 | 4 | /* ref: http://limulus.net/mdsplib */ 5 | /* 6 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 7 | Copyright (C) 2003 Eric McCarthy 8 | 9 | This library is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU Lesser General Public 11 | License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. 13 | 14 | This library is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public 20 | License along with this library; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | */ 23 | 24 | /********************************************************************/ 25 | /* */ 26 | /* Title: metar.h */ 27 | /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */ 28 | /* Date: 19 Jan 1996 */ 29 | /* Programmer: CARL MCCALLA */ 30 | /* Language: C/370 */ 31 | /* */ 32 | /* Abstract: METAR Decoder Header File. */ 33 | /* */ 34 | /* Modification History: */ 35 | /* 7 Jul 2001 by Eric McCarthy: Made suitable for */ 36 | /* use as header for the metar.a library. */ 37 | /* */ 38 | /********************************************************************/ 39 | 40 | /* Used in the METAR structs. */ 41 | #ifndef mdsp_bool 42 | #define mdsp_bool 43 | typedef unsigned short int MDSP_BOOL; 44 | #endif 45 | 46 | #define MAX_RUNWAYS 12 47 | #define MAX_CLOUD_GROUPS 6 48 | #define MAX_SURFACE_OBSCURATIONS 6 49 | #define MAX_PARTIAL_OBSCURATIONS 2 50 | 51 | typedef enum distance_unit { DIST_FEET, DIST_METERS } Distance_Unit; 52 | 53 | /*********************************************/ 54 | /* */ 55 | /* RUNWAY VISUAL RANGE STRUCTURE DECLARATION */ 56 | /* AND VARIABLE TYPE DEFINITION */ 57 | /* */ 58 | /*********************************************/ 59 | 60 | typedef struct runway_VisRange { 61 | char runway_designator[6]; 62 | MDSP_BOOL vrbl_visRange; 63 | MDSP_BOOL below_min_RVR; 64 | MDSP_BOOL above_max_RVR; 65 | int visRange; 66 | int Max_visRange; 67 | int Min_visRange; 68 | Distance_Unit distance_unit; 69 | } Runway_VisRange; 70 | 71 | /***********************************************/ 72 | /* */ 73 | /* DISPATCH VISUAL RANGE STRUCTURE DECLARATION */ 74 | /* AND VARIABLE TYPE DEFINITION */ 75 | /* */ 76 | /***********************************************/ 77 | 78 | typedef struct dispatch_VisRange { 79 | MDSP_BOOL vrbl_visRange; 80 | MDSP_BOOL below_min_DVR; 81 | MDSP_BOOL above_max_DVR; 82 | int visRange; 83 | int Max_visRange; 84 | int Min_visRange; 85 | } Dispatch_VisRange; 86 | 87 | /*****************************************/ 88 | /* */ 89 | /* CLOUD CONDITION STRUCTURE DECLARATION */ 90 | /* AND VARIABLE TYPE DEFINITION */ 91 | /* */ 92 | /*****************************************/ 93 | 94 | typedef struct cloud_Conditions { 95 | char cloud_type[5]; 96 | char cloud_hgt_char[4]; 97 | char other_cld_phenom[4]; 98 | int cloud_hgt_meters; 99 | } Cloud_Conditions; 100 | 101 | /*****************************************/ 102 | /* */ 103 | /* WIND GROUP DATA STRUCTURE DECLARATION */ 104 | /* AND VARIABLE TYPE DEFINITION */ 105 | /* */ 106 | /*****************************************/ 107 | 108 | typedef struct windstruct { 109 | char windUnits[ 4 ]; 110 | MDSP_BOOL windVRB; 111 | int windDir; 112 | int windSpeed; 113 | int windGust; 114 | } WindStruct; 115 | 116 | /*****************************************/ 117 | /* */ 118 | /* RECENT WX GROUP STRUCTURE DECLARATION */ 119 | /* AND VARIABLE TYPE DEFINITION */ 120 | /* */ 121 | /*****************************************/ 122 | 123 | typedef struct recent_wx { 124 | char Recent_weather[ 5 ]; 125 | int Bhh; 126 | int Bmm; 127 | int Ehh; 128 | int Emm; 129 | } Recent_Wx; 130 | 131 | /***************************************/ 132 | /* */ 133 | /* DECODED METAR STRUCTURE DECLARATION */ 134 | /* AND VARIABLE TYPE DEFINITION */ 135 | /* */ 136 | /***************************************/ 137 | 138 | typedef struct decoded_METAR { 139 | char synoptic_cloud_type[ 6 ]; 140 | char snow_depth_group[ 6 ]; 141 | char codeName[ 6 ]; 142 | char stnid[5]; 143 | char horiz_vsby[5]; 144 | char dir_min_horiz_vsby[3]; 145 | char vsby_Dir[ 3 ]; 146 | char WxObstruct[10][8]; 147 | char autoIndicator[5]; 148 | char VSBY_2ndSite_LOC[10]; 149 | char SKY_2ndSite_LOC[10]; 150 | char SKY_2ndSite[10]; 151 | char SectorVsby_Dir[ 3 ]; 152 | char ObscurAloft[ 12 ]; 153 | char ObscurAloftSkyCond[ 12 ]; 154 | char VrbSkyBelow[ 4 ]; 155 | char VrbSkyAbove[ 4 ]; 156 | char LTG_DIR[ 3 ]; 157 | char CloudLow; 158 | char CloudMedium; 159 | char CloudHigh; 160 | char CIG_2ndSite_LOC[10]; 161 | char VIRGA_DIR[3]; 162 | char TornadicType[15]; 163 | char TornadicLOC[10]; 164 | char TornadicDIR[4]; 165 | char TornadicMovDir[3]; 166 | char CHINO_LOC[6]; 167 | char VISNO_LOC[6]; 168 | char PartialObscurationAmt[MAX_PARTIAL_OBSCURATIONS][7]; 169 | char PartialObscurationPhenom[MAX_PARTIAL_OBSCURATIONS][12]; 170 | char SfcObscuration[MAX_SURFACE_OBSCURATIONS][10]; 171 | char TS_LOC[3]; 172 | char TS_MOVMNT[3]; 173 | 174 | MDSP_BOOL Indeterminant3_6HrPrecip; 175 | MDSP_BOOL Indeterminant_24HrPrecip; 176 | MDSP_BOOL CIGNO; 177 | MDSP_BOOL SLPNO; 178 | MDSP_BOOL ACFTMSHP; 179 | MDSP_BOOL NOSPECI; 180 | MDSP_BOOL FIRST; 181 | MDSP_BOOL LAST; 182 | MDSP_BOOL SunSensorOut; 183 | MDSP_BOOL AUTO; 184 | MDSP_BOOL COR; 185 | MDSP_BOOL NIL_rpt; 186 | MDSP_BOOL CAVOK; 187 | MDSP_BOOL RVRNO; 188 | MDSP_BOOL A_altstng; 189 | MDSP_BOOL Q_altstng; 190 | MDSP_BOOL VIRGA; 191 | MDSP_BOOL VOLCASH; 192 | MDSP_BOOL GR; 193 | MDSP_BOOL CHINO; 194 | MDSP_BOOL VISNO; 195 | MDSP_BOOL PNO; 196 | MDSP_BOOL PWINO; 197 | MDSP_BOOL FZRANO; 198 | MDSP_BOOL TSNO; 199 | MDSP_BOOL DollarSign; 200 | MDSP_BOOL PRESRR; 201 | MDSP_BOOL PRESFR; 202 | MDSP_BOOL Wshft_FROPA; 203 | MDSP_BOOL OCNL_LTG; 204 | MDSP_BOOL FRQ_LTG; 205 | MDSP_BOOL CNS_LTG; 206 | MDSP_BOOL CG_LTG; 207 | MDSP_BOOL IC_LTG; 208 | MDSP_BOOL CC_LTG; 209 | MDSP_BOOL CA_LTG; 210 | MDSP_BOOL DSNT_LTG; 211 | MDSP_BOOL AP_LTG; 212 | MDSP_BOOL VcyStn_LTG; 213 | MDSP_BOOL OVHD_LTG; 214 | MDSP_BOOL LightningVCTS; 215 | MDSP_BOOL LightningTS; 216 | MDSP_BOOL visibilityIsUpperBound; 217 | 218 | int TornadicDistance; 219 | int ob_hour; 220 | int ob_minute; 221 | int ob_date; 222 | int minWnDir; 223 | int maxWnDir; 224 | int VertVsby; 225 | int temp; 226 | int dew_pt_temp; 227 | int QFE; 228 | int hectoPasc_altstng; 229 | int char_prestndcy; 230 | int minCeiling; 231 | int maxCeiling; 232 | int WshfTime_hour; 233 | int WshfTime_minute; 234 | int min_vrbl_wind_dir; 235 | int max_vrbl_wind_dir; 236 | int PKWND_dir; 237 | int PKWND_speed; 238 | int PKWND_hour; 239 | int PKWND_minute; 240 | int SKY_2ndSite_Meters; 241 | int Ceiling; 242 | int Estimated_Ceiling; 243 | int SNINCR; 244 | int SNINCR_TotalDepth; 245 | int SunshineDur; 246 | int ObscurAloftHgt; 247 | int VrbSkyLayerHgt; 248 | int Num8thsSkyObscured; 249 | int CIG_2ndSite_Meters; 250 | int snow_depth; 251 | int BTornadicHour; 252 | int BTornadicMinute; 253 | int ETornadicHour; 254 | int ETornadicMinute; 255 | 256 | 257 | float SectorVsby; 258 | float WaterEquivSnow; 259 | float VSBY_2ndSite; 260 | float prevail_vsbySM; 261 | float prevail_vsbyM; 262 | float prevail_vsbyKM; 263 | float prestndcy; 264 | float precip_amt; 265 | float precip_24_amt; 266 | float maxtemp; 267 | float mintemp; 268 | float max24temp; 269 | float min24temp; 270 | float minVsby; 271 | float maxVsby; 272 | float hourlyPrecip; 273 | float TWR_VSBY; 274 | float SFC_VSBY; 275 | float Temp_2_tenths; 276 | float DP_Temp_2_tenths; 277 | float SLP; 278 | float GR_Size; 279 | 280 | double inches_altstng; 281 | 282 | Runway_VisRange RRVR[MAX_RUNWAYS]; 283 | Dispatch_VisRange DVR; 284 | Recent_Wx ReWx[3]; 285 | WindStruct winData; 286 | Cloud_Conditions cloudGroup[MAX_CLOUD_GROUPS]; 287 | 288 | } Decoded_METAR; 289 | 290 | 291 | /********************************************************************/ 292 | /* */ 293 | /* Title: decode_metar */ 294 | /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */ 295 | /* Date: 14 Sep 1994 */ 296 | /* Programmer: CARL MCCALLA */ 297 | /* Language: C/370 */ 298 | /* */ 299 | /* Abstract: decode_metar takes a pointer to a METAR report */ 300 | /* string as input, decodes the report, and */ 301 | /* puts the individual decoded/parsed groups into */ 302 | /* a structure that has the variable type */ 303 | /* Decoded_METAR. */ 304 | /* */ 305 | /* Input: string - a pointer to a METAR report character */ 306 | /* string. */ 307 | /* */ 308 | /* Output: Mptr - a pointer to a structure that has the */ 309 | /* variable type Decoded_METAR. */ 310 | /* */ 311 | /* Modification History: */ 312 | /* 3 Jul 2001 by Eric McCarthy: Added stringCpy */ 313 | /* so cosnt char *'s could be passed in. */ 314 | /* */ 315 | /********************************************************************/ 316 | 317 | int decode_metar( const char *instring , Decoded_METAR *Mptr ); 318 | 319 | 320 | 321 | /********************************************************************/ 322 | /* */ 323 | /* Title: print_decoded_metar */ 324 | /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */ 325 | /* Date: 15 Sep 1994 */ 326 | /* Programmer: CARL MCCALLA */ 327 | /* Language: C/370 */ 328 | /* */ 329 | /* Abstract: print_decoded_metar */ 330 | /* prints, in order of the ASOS METAR */ 331 | /* format, all non-initialized members of the structure */ 332 | /* addressed by the Decoded_METAR pointer. */ 333 | /* */ 334 | /* External Functions Called: */ 335 | /* None. */ 336 | /* */ 337 | /* Input: Mptr - ptr to a decoded_METAR structure. */ 338 | /* */ 339 | /* Output: NONE */ 340 | /* */ 341 | /* Modification History: */ 342 | /* None. */ 343 | /* */ 344 | /********************************************************************/ 345 | 346 | void print_decoded_metar( Decoded_METAR *Mptr ); 347 | 348 | 349 | /********************************************************************/ 350 | /* */ 351 | /* Title: decode_net_metar */ 352 | /* Date: 24 Jul 2001 */ 353 | /* Programmer: Eric McCarthy */ 354 | /* Language: C */ 355 | /* */ 356 | /* Abstract: decode_net_metar */ 357 | /* The METARs supplied by the NWS server need to */ 358 | /* be reformatted before they can be sent through */ 359 | /* decode_metar. */ 360 | /* This calls dcdMETAR on the correctly */ 361 | /* formated METAR. */ 362 | /* */ 363 | /* Input: a pointer to a METAR string from a NWS server */ 364 | /* */ 365 | /* Output: Mptr - a pointer to a structure that has the */ 366 | /* variable type Decoded_METAR. */ 367 | /* */ 368 | /* Modification History: */ 369 | /* None. */ 370 | /* */ 371 | /********************************************************************/ 372 | 373 | int decode_net_metar (const char *instring, Decoded_METAR *Mptr); 374 | 375 | 376 | /********************************************************************/ 377 | /* */ 378 | /* Title: sprint_metar */ 379 | /* Date: 24 Jul 2001 */ 380 | /* Programmer: Eric McCarthy */ 381 | /* Language: C */ 382 | /* */ 383 | /* Abstract: sprint_metar */ 384 | /* Does what print_decoded_metar does, but into a string. */ 385 | /* */ 386 | /* Input: string containing the printout, decoded METAR */ 387 | /* */ 388 | /* Modification History: */ 389 | /* None. */ 390 | /* */ 391 | /********************************************************************/ 392 | 393 | void sprint_metar( char *outstring, Decoded_METAR *Mptr ); 394 | 395 | 396 | #endif // MDSPLIB_METAR_H__ 397 | -------------------------------------------------------------------------------- /src/antoi.c: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include 21 | 22 | 23 | /********************************************************************/ 24 | /* */ 25 | /* Title: antoi */ 26 | /* Date: Jan 28, 1991 */ 27 | /* Organization: W/OSO242 - Graphics and Display Section */ 28 | /* Programmer: Allan Darling */ 29 | /* Language: C/370 */ 30 | /* */ 31 | /* Abstract: This function will convert a character array */ 32 | /* (string) of length (len) into an integer. */ 33 | /* The integer is created via a call to the */ 34 | /* function atoi. This function extends the */ 35 | /* functionality of atoi by removing the */ 36 | /* requirement for a sentinal delimited string */ 37 | /* as input. */ 38 | /* */ 39 | /* Input: - Pointer to an array of characters. */ 40 | /* - Integer indicating the number of character to include */ 41 | /* in the conversion. */ 42 | /* */ 43 | /* Output:- An integer corresponding to the value in the character */ 44 | /* array or MAXNEG (-2147483648) if the function is */ 45 | /* unable to acquire system storage. */ 46 | /* */ 47 | /* Modification History: */ 48 | /* None */ 49 | /* */ 50 | /********************************************************************/ 51 | 52 | int antoi(char * string, int len) 53 | { 54 | char * tmpstr; 55 | int i, retval; 56 | 57 | tmpstr = malloc((len+1) * sizeof(char)); 58 | 59 | if (tmpstr == NULL) return (-2147483648); 60 | 61 | for (i = 0; i < len; i++) 62 | tmpstr[i] = string[i]; 63 | 64 | tmpstr[len] = '\0'; 65 | 66 | retval = atoi(tmpstr); 67 | 68 | free(tmpstr); 69 | 70 | return(retval); 71 | 72 | } /* end antoi */ 73 | 74 | 75 | // vim: set ts=4 sw=4 sts=4 noet : 76 | -------------------------------------------------------------------------------- /src/charcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "local.h" /* standard header file */ 21 | 22 | /********************************************************************/ 23 | /* */ 24 | /* Title: charcmp */ 25 | /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */ 26 | /* Date: 12 Dec 1995 */ 27 | /* Programmer: CINDY L. CHONG */ 28 | /* Language: C/370 */ 29 | /* */ 30 | /* Abstract: This function will compare each character in the */ 31 | /* string match with each character in the pattern */ 32 | /* which is made up of characters. The str can */ 33 | /* be longer than the pattern. */ 34 | /* */ 35 | /* External Functions Called: */ 36 | /* None. */ 37 | /* */ 38 | /* Input: str is a pointer to char */ 39 | /* pattern is a pointer to char */ 40 | /* */ 41 | /* Output: Return true if str matches pattern, */ 42 | /* otherwise, return false */ 43 | /* */ 44 | /* Modification History: */ 45 | /* None. */ 46 | /* */ 47 | /********************************************************************/ 48 | MDSP_BOOL charcmp(char *str, char *pattern) 49 | { 50 | 51 | 52 | /* Loop while str and pattern is not equal to null, then */ 53 | /* inscreases str and pattern by one */ 54 | 55 | for (; *pattern != '\0'; pattern++) 56 | { 57 | if (*str == '\0') 58 | return FALSE; 59 | 60 | /* If pattern match str, then increase str and jump out the */ 61 | /* case and read next char of the str and pattern */ 62 | 63 | if ( isspace(*pattern) ) 64 | pattern = nxtalpha(pattern); 65 | 66 | switch( *pattern ) 67 | { 68 | case 'c': 69 | if ( !isalnum(*str++) ) 70 | { 71 | return FALSE; 72 | } 73 | break; 74 | 75 | case 'a': 76 | if ( !isalpha(*str) ) 77 | { 78 | return FALSE; 79 | } 80 | str++; 81 | break; 82 | 83 | case 'n': 84 | if ( !iscntrl(*str++) ) 85 | { 86 | return FALSE; 87 | } 88 | break; 89 | 90 | case 'd': 91 | if ( !isdigit(*str) ) 92 | { 93 | return FALSE; 94 | } 95 | str++; 96 | break; 97 | 98 | case 'g': 99 | if ( !isgraph(*str++) ) 100 | { 101 | return FALSE; 102 | } 103 | break; 104 | 105 | case 'i': 106 | if ( !islower(*str++) ) 107 | { 108 | return FALSE; 109 | } 110 | break; 111 | 112 | case 'p': 113 | if ( !isprint(*str++) ) 114 | { 115 | return FALSE; 116 | } 117 | break; 118 | 119 | case 't': 120 | if ( !ispunct(*str++) ) 121 | { 122 | return FALSE; 123 | } 124 | break; 125 | 126 | case 'w': 127 | if ( !isspace(*str++) ) 128 | { 129 | return FALSE; 130 | } 131 | break; 132 | 133 | case 'u': 134 | if ( !isupper(*str++) ) 135 | { 136 | return FALSE; 137 | } 138 | break; 139 | 140 | case 's': 141 | if (*str++ != ' ') 142 | { 143 | return FALSE; 144 | } 145 | break; 146 | 147 | case 'm': 148 | if ( !isspace(*str) ) 149 | { 150 | return FALSE; 151 | } 152 | else 153 | { 154 | while ( isspace(*str) ) 155 | str++; 156 | } 157 | break; 158 | 159 | case '\'': 160 | pattern++; 161 | if (*pattern != *str) 162 | { 163 | return FALSE; 164 | } 165 | pattern++; 166 | str++; 167 | break; 168 | 169 | default: 170 | return FALSE; 171 | 172 | } /* end switch */ 173 | 174 | } /* end for */ 175 | 176 | return (TRUE); 177 | } 178 | 179 | // vim: set ts=4 sw=4 sts=4 noet : 180 | -------------------------------------------------------------------------------- /src/fracpart.c: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "metar_structs.h" 21 | 22 | /********************************************************************/ 23 | /* */ 24 | /* Title: fracPart */ 25 | /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */ 26 | /* Date: 13 Jun 1995 */ 27 | /* Programmer: CARL MCCALLA */ 28 | /* Language: C/370 */ 29 | /* */ 30 | /* Abstract: Convert a character string fraction into a */ 31 | /* decimal (floating point) number. */ 32 | /* */ 33 | /* External Functions Called: */ 34 | /* None. */ 35 | /* */ 36 | /* Input: string - a pointer to a character string frac- */ 37 | /* tion. */ 38 | /* Output: A decimal (floating point) number. */ 39 | /* */ 40 | /* Modification History: */ 41 | /* None. */ 42 | /* */ 43 | /********************************************************************/ 44 | 45 | float fracPart( const char *instring ) 46 | { 47 | char buf[ 32 ], 48 | *slash; 49 | 50 | float numerator, 51 | denominator; 52 | 53 | slash = strchr(instring, '/'); 54 | 55 | if (slash == NULL) { 56 | return ((float) atoi(instring)); 57 | } 58 | 59 | memset(buf , '\0', sizeof(buf)); 60 | if (slash - instring >= sizeof(buf)) { 61 | /* prevent buffer overflow */ 62 | return ((float) MAXINT); 63 | } 64 | strncpy( buf, instring, slash - instring); 65 | 66 | numerator = (float) atoi(buf); 67 | 68 | denominator = (float) atoi(slash + 1); 69 | 70 | if( denominator == 0.0 ) 71 | return ((float) MAXINT); 72 | else 73 | return (numerator/denominator); 74 | 75 | } 76 | 77 | // vim: set ts=4 sw=4 sts=4 noet : 78 | -------------------------------------------------------------------------------- /src/local.h: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | /*********************************************************************/ 21 | /* */ 22 | /* Title: local h */ 23 | /* Updated: 10 June 1996 */ 24 | /* Organization: W/OSO242 - Graphics and Display Section */ 25 | /* Language: C/370 */ 26 | /* */ 27 | /* Abstract: */ 28 | /* This header file provides all function definitions necessary for */ 29 | /* the OSO242 C function library. */ 30 | /* */ 31 | /*********************************************************************/ 32 | 33 | #ifndef locallib_defined 34 | #define locallib_defined 35 | 36 | 37 | 38 | /*****************/ 39 | /* Include Files */ 40 | /*****************/ 41 | 42 | #include 43 | #include 44 | /* #include Includes IBM specific debugging libraries */ 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | 59 | 60 | 61 | /********************/ 62 | /* Standard Defines */ 63 | /********************/ 64 | 65 | #define FALSE 0 /* boolean value */ 66 | #define MAXINT INT_MAX /* maximum integer */ 67 | #define MININT INT_MIN /* minimum integer */ 68 | #define MAXNEG INT_MIN /* minimum integer */ 69 | #define NO FALSE /* boolean value */ 70 | #define TRUE 1 /* boolean value */ 71 | #define TRUNCATED -1 /* indicates truncation */ 72 | #define YES TRUE /* boolean value */ 73 | 74 | 75 | /*****************/ 76 | /* Macro defines */ 77 | /*****************/ 78 | 79 | #define ABS(x) (((x) < 0) ? -(x) : (x)) 80 | #define clearscrn system("CLRSCRN") 81 | #define assgndev(d, v) v = 0x##d 82 | #define DIM(a) (sizeof(a) / sizeof(a[0])) 83 | #define FOREVER for(;;) /* endless loop */ 84 | #define getln(s, n) ((fgets(s, n, stdin)==NULL) ? EOF : strlen(s)) 85 | #define IMOD(i, j) (((i) % (j)) < 0 ? ((i) % (j))+(j) : ((i) % (j))) 86 | #define IN_RANGE(n, lo, hi) ((lo) <= (n) && (n) <= (hi)) 87 | #define LOOPDN(r, n) for ((r) = (n)+1; --(r) > 0;) 88 | #define MAX(x, y) (((x) < (y)) ? (y) : (x)) 89 | #ifndef _WIN32 90 | #define max(x, y) (((x) < (y)) ? (y) : (x)) 91 | #endif 92 | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 93 | #define min(x, y) (((x) < (y)) ? (x) : (y)) 94 | #define STREQ(s, t) (strcmp(s, t) == 0) 95 | #define STRGT(s, t) (strcmp(s, t) > 0) 96 | #define STRLT(s, t) (strcmp(s, t) < 0) 97 | #define STRNEQ(s, t, l) (strncmp(s, t, l) == 0) 98 | #define STRNGT(s, t, l) (strncmp(s, t, l) > 0) 99 | #define STRNLT(s, t, l) (strncmp(s, t, l) < 0) 100 | #define SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t)) 101 | 102 | 103 | /*********************************************************************/ 104 | /* */ 105 | /* Memory allocation debugging routines */ 106 | /* */ 107 | /*********************************************************************/ 108 | 109 | #ifdef MEMDEBUG 110 | 111 | void *mallocx(size_t, char *, int); 112 | void *callocx(size_t, size_t, char *, int); 113 | void *reallocx(void *, size_t, char *, int); 114 | void freex(void *, char *, int); 115 | 116 | #define malloct(x) mallocx((x), __FILE__, __LINE__) 117 | #define calloct(x, y) callocx((x), (y), __FILE__, __LINE__) 118 | #define realloct(x, y) reallocx((x), (y), __FILE__, __LINE__) 119 | #define freet(x) freex((x), __FILE__, __LINE__) 120 | 121 | #define malloc malloct 122 | #define calloc calloct 123 | #define realloc realloct 124 | #define free freet 125 | 126 | #endif 127 | 128 | 129 | 130 | /*********************************************************************/ 131 | /* */ 132 | /* General typedefs */ 133 | /* */ 134 | /*********************************************************************/ 135 | 136 | typedef unsigned char byte; 137 | 138 | #ifndef mdsp_bool 139 | #define mdsp_bool 140 | typedef unsigned short int MDSP_BOOL; 141 | #endif 142 | 143 | 144 | typedef unsigned short int Devaddr; 145 | 146 | typedef struct diskaddr { 147 | int cylinder; 148 | int track; 149 | int record; 150 | } Diskaddr; 151 | 152 | 153 | typedef struct record_id { 154 | 155 | char id[8]; 156 | time_t write_timestamp; 157 | 158 | } Record_ID; 159 | 160 | 161 | typedef struct location { 162 | 163 | union { 164 | unsigned bsn; 165 | char cs[9]; 166 | unsigned short msn; 167 | } loc; 168 | 169 | unsigned location_is_bsn:1, 170 | location_is_cs:1, 171 | location_is_msn:1; 172 | 173 | } Location; 174 | 175 | 176 | 177 | /*********************************************************************/ 178 | /*********************************************************************/ 179 | /* */ 180 | /* */ 181 | /* Functions specific defines, typedefs, and structures */ 182 | /* */ 183 | /* */ 184 | /*********************************************************************/ 185 | /*********************************************************************/ 186 | 187 | 188 | 189 | /*********************************************************************/ 190 | /* */ 191 | /* Function prototype and structure(s) used in - */ 192 | /* */ 193 | /* bldstree - Build station information tree */ 194 | /* delstree - Delete station information tree */ 195 | /* getstinf - Get station information from tree */ 196 | /* */ 197 | /*********************************************************************/ 198 | 199 | typedef struct stn_info_node { 200 | int key; 201 | int block; 202 | int station; 203 | int latitude; 204 | int longitude; 205 | int elev; 206 | struct stn_info_node * right; 207 | struct stn_info_node * left; 208 | } Stninfo; 209 | 210 | struct stn_info_node *bldstree(void); 211 | void delstree(struct stn_info_node *); 212 | struct stn_info_node *getstinf(struct stn_info_node *, 213 | int, 214 | int); 215 | 216 | 217 | 218 | /*********************************************************************/ 219 | /* */ 220 | /* Function prototype and structure(s) used in - */ 221 | /* */ 222 | /* capqread - Read bulletins from CAPQ chain */ 223 | /* */ 224 | /*********************************************************************/ 225 | 226 | typedef struct CAPQ_data { 227 | char * bulletin; 228 | int bulletin_length; 229 | char * WMO_heading; 230 | char * AFOS_pil; 231 | char * current_CAPQ_end_address; 232 | int start_offset; 233 | int record_count; 234 | int end_offset; 235 | char * bulletin_address; 236 | int input_line; 237 | int receive_line; 238 | int receive_hour; 239 | int receive_minute; 240 | int CAPQ_day; 241 | int CAPQ_hour; 242 | int CAPQ_minute; 243 | int rc; 244 | char flag1; 245 | char flag2; 246 | } CAPQdata; 247 | 248 | struct CAPQ_data * capqread (char *, ...); 249 | 250 | 251 | 252 | /*********************************************************************/ 253 | /* */ 254 | /* Function prototype and structure(s) used in - */ 255 | /* */ 256 | /* mdadread - Read bulletins from MDAD chain */ 257 | /* */ 258 | /*********************************************************************/ 259 | 260 | typedef struct MDAD_data { 261 | char * bulletin; 262 | int bulletin_length; 263 | char * WMO_heading; 264 | char * AFOS_pil; 265 | char * current_MDAD_end_address; 266 | int start_offset; 267 | int record_count; 268 | int end_offset; 269 | char * bulletin_address; 270 | int input_line; 271 | int receive_line; 272 | int receive_hour; 273 | int receive_minute; 274 | int MDAD_year; 275 | int MDAD_month; 276 | int MDAD_day; 277 | int MDAD_hour; 278 | int MDAD_minute; 279 | int rc; 280 | int part_number; 281 | int number_of_parts; 282 | char MDAD_flag; 283 | char flag1; 284 | char flag2; 285 | char flag3; 286 | char MDAD_flag2; 287 | } MDADdata; 288 | 289 | MDADdata * mdadread (char *, ...); 290 | MDADdata * mdupread (char *, ...); 291 | MDADdata * mdadrd2 (char *, ...); 292 | 293 | MDADdata * mdadscan (char *, ...); 294 | MDADdata * mdupscan (char *, ...); 295 | 296 | void mdadinpt ( MDADdata *, char, MDSP_BOOL ); 297 | 298 | char * mdadnxtr ( void ); 299 | char * mdadnxtk ( void ); 300 | 301 | 302 | #define MDAD_HISTORY_LIMIT 39 303 | 304 | typedef 305 | struct MDAD_history_entry 306 | { 307 | unsigned short hour; 308 | unsigned short minute; 309 | Diskaddr MDAD_chain_addr; 310 | } 311 | MDAD_History_Entry; 312 | 313 | typedef 314 | struct MDAD_history 315 | { 316 | MDAD_History_Entry history_array[MDAD_HISTORY_LIMIT]; 317 | } 318 | MDAD_History; 319 | 320 | MDAD_History *mdadhist ( void ); 321 | 322 | 323 | /*********************************************************************/ 324 | /* */ 325 | /* Function prototype and structure(s) used in - */ 326 | /* */ 327 | /* gethdgi - Get bulletin heading information */ 328 | /* */ 329 | /*********************************************************************/ 330 | 331 | typedef struct bltn_heading_info { 332 | int bltn_day; 333 | int bltn_hour; 334 | int bltn_min; 335 | int rtd_present; 336 | int cor_present; 337 | int amd_present; 338 | char * first_report; 339 | char TTAAii[7]; 340 | char CCCC[5]; 341 | char amd_seq; 342 | char cor_seq; 343 | char rtd_seq; 344 | } Abbrevhdg; 345 | 346 | Abbrevhdg *gethdgi(char * ); 347 | 348 | 349 | 350 | /*********************************************************************/ 351 | /* */ 352 | /* Function prototype and structure(s) used in - */ 353 | /* */ 354 | /* getime - Get current system time */ 355 | /* suspend - Delay execution until specified minute boundary */ 356 | /* */ 357 | /*********************************************************************/ 358 | 359 | 360 | typedef struct tm_struct{ 361 | int hour; 362 | int min; 363 | } Stime; 364 | 365 | Stime *gettime(void); 366 | int suspend(Stime *, int); 367 | int timediff(Stime *, Stime *); 368 | #define timecmp timediff 369 | 370 | 371 | 372 | /*********************************************************************/ 373 | /* */ 374 | /* Function prototype and structure(s) used in - */ 375 | /* */ 376 | /* rdtaend - Specify rdtaread Ending Address */ 377 | /* rdtaread - Read From RGTR Data Tank */ 378 | /* rdtastrt - Specify rdtaread Starting Address */ 379 | /* rdtatend - Specify rdtaread End Time */ 380 | /* rdtatnke - Specify rdtaread Ending Address */ 381 | /* rdtarstr - Specify rdtaread Start Time */ 382 | /* */ 383 | /*********************************************************************/ 384 | 385 | typedef struct rgtrdata { 386 | Diskaddr forward_chain; 387 | Diskaddr bulletin_addr; 388 | int receive_line; 389 | int receive_day; 390 | Stime receive_time; 391 | Stime RGTR_time; 392 | int length; 393 | char *bulletin; 394 | char datatype; 395 | } RGTRdata; 396 | 397 | int rdtaend(char, Diskaddr *); 398 | int rdtaread(RGTRdata *); 399 | int rdtastrt(char, Diskaddr *); 400 | int rdtatend (char, Stime *); 401 | int rdtatnke(char); 402 | int rdtatstr(char, Stime *); 403 | void rdtainit(void); 404 | 405 | 406 | 407 | /*********************************************************************/ 408 | /* */ 409 | /* Typedefs and function prototypes for bulletin and report parsing */ 410 | /* functions. */ 411 | /* */ 412 | /*********************************************************************/ 413 | 414 | 415 | 416 | typedef struct rptNode { 417 | char *rptPtr; 418 | int rptLength; 419 | struct rptNode* next; 420 | } RptNode; 421 | 422 | 423 | typedef struct synpBltn { 424 | Abbrevhdg heading; 425 | short int day; 426 | short int hour; 427 | int reportCount; 428 | RptNode *rptList; 429 | MDSP_BOOL valid; 430 | } SynpBltn; 431 | 432 | 433 | typedef struct shipBltn { 434 | Abbrevhdg heading; 435 | int reportCount; 436 | RptNode *rptList; 437 | MDSP_BOOL valid; 438 | } ShipBltn; 439 | 440 | 441 | typedef struct tepiBltn { 442 | Abbrevhdg heading; 443 | int reportCount; 444 | RptNode *rptList; 445 | MDSP_BOOL valid; 446 | } TePiBltn; 447 | 448 | 449 | typedef struct drftBltn { 450 | Abbrevhdg heading; 451 | int reportCount; 452 | RptNode *rptList; 453 | MDSP_BOOL valid; 454 | } DrftBltn; 455 | 456 | 457 | typedef struct airpBltn { 458 | Abbrevhdg heading; 459 | int reportCount; 460 | RptNode *rptList; 461 | MDSP_BOOL valid; 462 | } AirpBltn; 463 | 464 | 465 | typedef struct amdrBltn { 466 | Abbrevhdg heading; 467 | short int day; 468 | short int hour; 469 | int reportCount; 470 | RptNode *rptList; 471 | MDSP_BOOL valid; 472 | } AmdrBltn; 473 | 474 | 475 | typedef struct bthyBltn { 476 | Abbrevhdg heading; 477 | int reportCount; 478 | RptNode *rptList; 479 | MDSP_BOOL valid; 480 | } BthyBltn; 481 | 482 | 483 | typedef struct tescBltn { 484 | Abbrevhdg heading; 485 | int reportCount; 486 | RptNode *rptList; 487 | MDSP_BOOL valid; 488 | } TescBltn; 489 | 490 | 491 | typedef struct tracBltn { 492 | Abbrevhdg heading; 493 | int reportCount; 494 | RptNode *rptList; 495 | MDSP_BOOL valid; 496 | } TracBltn; 497 | 498 | 499 | typedef struct climBltn { 500 | Abbrevhdg heading; 501 | int reportCount; 502 | int month; 503 | int year; 504 | RptNode *rptList; 505 | MDSP_BOOL valid; 506 | } ClimBltn; 507 | 508 | 509 | typedef struct clmtBltn { 510 | Abbrevhdg heading; 511 | int reportCount; 512 | int month; 513 | int year; 514 | RptNode *rptList; 515 | MDSP_BOOL valid; 516 | } ClmtBltn; 517 | 518 | 519 | typedef struct metBltn { 520 | Abbrevhdg heading; 521 | int reportCount; 522 | RptNode *rptList; 523 | MDSP_BOOL valid; 524 | short int day; /* -1 indicates missing/invalid */ 525 | short int hour; /* -1 indicates missing/invalid */ 526 | short int min; /* -1 indicates missing/invalid */ 527 | } MetBltn; 528 | 529 | 530 | typedef struct saoBltn { 531 | Abbrevhdg heading; 532 | int reportCount; 533 | RptNode *rptList; 534 | MDSP_BOOL valid; 535 | } SAOBltn; 536 | 537 | 538 | typedef struct prBltn { 539 | Abbrevhdg heading; 540 | int reportCount; 541 | RptNode *rptList; 542 | MDSP_BOOL valid; 543 | } PRBltn; 544 | 545 | 546 | typedef struct tafBltn { 547 | Abbrevhdg heading; 548 | int reportCount; 549 | RptNode *rptList; 550 | MDSP_BOOL valid; 551 | } TafBltn; 552 | 553 | 554 | typedef struct arepBltn{ 555 | Abbrevhdg heading; 556 | int reportCount; 557 | RptNode *rptList; 558 | MDSP_BOOL valid; 559 | }ArepBltn; 560 | 561 | typedef struct metrRptP { 562 | char locind[4]; 563 | int groupCount; 564 | short int day; /* -1 indicates missing or invalid */ 565 | short int hour; /* -1 indicates missing or invalid */ 566 | short int min; /* -1 indicates missing or invalid */ 567 | MDSP_BOOL valid; 568 | } MetrRptP; 569 | 570 | 571 | typedef struct saoRptP { 572 | char locind[4]; 573 | int groupCount; 574 | short int hour; /* -1 indicates missing or invalid */ 575 | short int min; /* -1 indicates missing or invalid */ 576 | MDSP_BOOL valid; 577 | } SAORptP; 578 | 579 | 580 | typedef struct prRptP { 581 | char locind[4]; 582 | int groupCount; 583 | short int hour; /* -1 indicates missing or invalid */ 584 | short int min; /* -1 indicates missing or invalid */ 585 | MDSP_BOOL valid; 586 | } PRRptP; 587 | 588 | 589 | typedef struct tafRptP { 590 | char locind[4]; 591 | int groupCount; 592 | short int YY; 593 | short int GG; 594 | short int validPeriod; 595 | MDSP_BOOL ammendment; 596 | MDSP_BOOL correction; 597 | MDSP_BOOL valid; 598 | } TafRptP; 599 | 600 | 601 | typedef struct synpRptP { 602 | short int II; 603 | short int iii; 604 | int groupCount; 605 | MDSP_BOOL valid; 606 | } SynpRptP; 607 | 608 | 609 | typedef struct climRptP { 610 | short int II; 611 | short int iii; 612 | int groupCount; 613 | MDSP_BOOL valid; 614 | } ClimRptP; 615 | 616 | 617 | typedef struct clmtRptP { 618 | short int II; 619 | short int iii; 620 | int groupCount; 621 | MDSP_BOOL valid; 622 | } ClmtRptP; 623 | 624 | 625 | typedef struct tepiRptP { 626 | short int II; 627 | short int iii; 628 | short int YY; 629 | short int GG; 630 | short int quad; 631 | short int ulatitude; 632 | short int ulongitude; 633 | int msquare; 634 | int latitude; 635 | int longitude; 636 | int groupCount; 637 | char callsign[15]; 638 | char type; 639 | char part; 640 | MDSP_BOOL valid; 641 | } TePiRptP; 642 | 643 | 644 | SynpBltn *pbsynp(char *); 645 | ShipBltn *pbship(char *); 646 | TePiBltn *pbtepi(char *); 647 | DrftBltn *pbdrft(char *); 648 | AirpBltn *pbairp(char *); 649 | AmdrBltn *pbamdr(char *); 650 | BthyBltn *pbbthy(char *); 651 | TescBltn *pbtesc(char *); 652 | TracBltn *pbtrac(char *); 653 | ClimBltn *pbclim(char *); 654 | ClmtBltn *pbclmt(char *); 655 | MetBltn *pbmetr(char *); 656 | MetBltn *pbspec(char *); 657 | TafBltn *pbtaf(char *); 658 | TafBltn *pbtaf2(char *); 659 | TafBltn *pbtaf3(char *); 660 | TafBltn *pbtaf4(char *); 661 | SAOBltn *pbsao(char *); 662 | PRBltn *pbpirep(char *); 663 | ArepBltn *pbairep(char *); 664 | 665 | SynpRptP *prpsynp(char *, int); 666 | TePiRptP *prptepi(char *, int); 667 | ClimRptP *prpclim(char *, int); 668 | ClmtRptP *prpclmt(char *, int); 669 | MetrRptP *prpmetr(char *, int); 670 | TafRptP *prptaf(char *, int); 671 | TafRptP *prptaf2(char *, int); 672 | TafRptP *prptaf3(char *, int); 673 | TafRptP *prptaf4(char *, int); 674 | SAORptP *prpsao(char *, int); 675 | PRRptP *prppirep(char *, int); 676 | 677 | 678 | 679 | 680 | /*********************************************************************/ 681 | /* */ 682 | /* Structures and Function Prototypes for RRN physical I/O */ 683 | /* */ 684 | /*********************************************************************/ 685 | 686 | 687 | typedef struct RRN_device { 688 | 689 | char name[44], 690 | ownerid[8]; 691 | 692 | unsigned short dev_addr, 693 | base_cylinder, 694 | base_track, 695 | base_record, 696 | max_cylinder, 697 | max_track, 698 | max_record, 699 | records_per_track, 700 | tracks_per_cylinder, 701 | record_length; 702 | 703 | } RRN_Device; 704 | 705 | 706 | MDSP_BOOL readrrn(char *device_name, 707 | unsigned int rrn, 708 | void *input_buffer, 709 | unsigned int read_count); 710 | 711 | MDSP_BOOL writerrn(char *device_name, 712 | unsigned int rrn, 713 | void *output_buffer, 714 | unsigned int write_count); 715 | 716 | RRN_Device *devinfo(char *device_name); 717 | 718 | MDSP_BOOL valid_dn(char *device_name); 719 | 720 | 721 | 722 | /*********************************************************************/ 723 | /* */ 724 | /* Function prototype for string value test functions. */ 725 | /* */ 726 | /*********************************************************************/ 727 | 728 | 729 | int sisalnum(char *); 730 | int sisalpha(char *); 731 | int siscntrl(char *); 732 | int sisdigit(char *); 733 | int sisgraph(char *); 734 | int sislower(char *); 735 | int sisprint(char *); 736 | int sispunct(char *); 737 | int sisspace(char *); 738 | int sisupper(char *); 739 | int sisxdigi(char *); 740 | 741 | int nisalnum(char *, int); 742 | int nisalpha(char *, int); 743 | int niscntrl(char *, int); 744 | int nisdigit(char *, int); 745 | int nisgraph(char *, int); 746 | int nislower(char *, int); 747 | int nisprint(char *, int); 748 | int nispunct(char *, int); 749 | int nisspace(char *, int); 750 | int nisupper(char *, int); 751 | int nisxdigi(char *, int); 752 | 753 | char *nxtalnum(char *); 754 | char *nxtalpha(char *); 755 | char *nxtcntrl(char *); 756 | char *nxtdigit(char *); 757 | char *nxtgraph(char *); 758 | char *nxtlower(char *); 759 | char *nxtprint(char *); 760 | char *nxtpunct(char *); 761 | char *nxtspace(char *); 762 | char *nxtupper(char *); 763 | char *nxtxdigi(char *); 764 | 765 | char *lstalnum(char *, int); 766 | char *lstalpha(char *, int); 767 | char *lstcntrl(char *, int); 768 | char *lstdigit(char *, int); 769 | char *lstgraph(char *, int); 770 | char *lstlower(char *, int); 771 | char *lstprint(char *, int); 772 | char *lstpunct(char *, int); 773 | char *lstspace(char *, int); 774 | char *lstupper(char *, int); 775 | char *lstxdigi(char *, int); 776 | 777 | 778 | /*********************************************************************/ 779 | /* */ 780 | /* Enumeration type and declaration for code form identification */ 781 | /* function */ 782 | /* */ 783 | /*********************************************************************/ 784 | 785 | 786 | typedef 787 | enum codeform {AIREP, AMDAR, ARFOR, ARMET, BATHY, CLIMAT, CLIMAT_SHIP, 788 | CLIMAT_TEMP, CLIMAT_TEMP_SHIP, CODAR, DRIFTER, FC, 789 | HYFOR, IAC, IAC_FLEET, ICEAN, METAR, PILOT, PILOT_MOBILE, 790 | PILOT_SHIP, RECCO, ROCOB, ROCOB_SHIP, ROFOR, SAO, PIREP, 791 | SATEM, SATOB, SHIP, SPECI, SYNOP, TAF, TEMP, TEMP_DROP, 792 | TEMP_MOBILE, TEMP_SHIP, TESAC, TRACKOB, WAVEOB, 793 | UNKNOWN_FORM, TEMP_A, TEMP_B, TEMP_C, TEMP_D, 794 | TEMP_DROP_A, TEMP_DROP_B, TEMP_DROP_C, TEMP_DROP_D, 795 | TEMP_MOBILE_A, TEMP_MOBILE_B, TEMP_MOBILE_C, 796 | TEMP_MOBILE_D, TEMP_SHIP_A, TEMP_SHIP_B, TEMP_SHIP_C, 797 | TEMP_SHIP_D, PILOT_A, PILOT_B, PILOT_C, PILOT_D, 798 | PILOT_MOBILE_A, PILOT_MOBILE_B, PILOT_MOBILE_C, 799 | PILOT_MOBILE_D, PILOT_SHIP_A, PILOT_SHIP_B, 800 | PILOT_SHIP_C, PILOT_SHIP_D } 801 | CodeForm; 802 | 803 | CodeForm idcode(char *); 804 | 805 | char *codename(CodeForm); 806 | CodeForm name2cf ( char * ); 807 | 808 | 809 | 810 | /********************************************************************/ 811 | /* */ 812 | /* Additional Bulletin and Report Parsing Structures and Routines */ 813 | /* */ 814 | /********************************************************************/ 815 | 816 | typedef struct mespBltn { 817 | Abbrevhdg heading; 818 | int reportCount; 819 | RptNode *rptList; 820 | CodeForm type; 821 | MDSP_BOOL valid; 822 | short int day; /* -1 indicates missing/invalid */ 823 | short int hour; /* -1 indicates missing/invalid */ 824 | short int min; /* -1 indicates missing/invalid */ 825 | } MeSpBltn; 826 | 827 | 828 | typedef struct mespRptP { 829 | char locind[4]; 830 | int groupCount; 831 | CodeForm type; 832 | char *rptStart; 833 | int rptLen; 834 | short int day; /* -1 indicates missing or invalid */ 835 | short int hour; /* -1 indicates missing or invalid */ 836 | short int min; /* -1 indicates missing or invalid */ 837 | MDSP_BOOL valid; 838 | } MeSpRptP; 839 | 840 | 841 | MeSpBltn *pbmesp(char *); 842 | 843 | MeSpRptP *prpmesp(char *, int); 844 | 845 | MeSpBltn *tpbmesp(char *); 846 | 847 | MeSpRptP *tprpmesp(char *, int); 848 | 849 | 850 | 851 | /*********************************************************************/ 852 | /* */ 853 | /* String manipulation functions */ 854 | /* */ 855 | /*********************************************************************/ 856 | 857 | 858 | char *strnlf(char *, size_t); 859 | char *strnmid(char *, size_t, size_t); 860 | char *strnrt(char *, size_t); 861 | char *strrstr(char *, char *); 862 | char *strcentr(char *, size_t); 863 | char *strdel(char *, char *, size_t); 864 | char *strins(char *, char *, char *); 865 | char *strljust(char * , size_t); 866 | char *strltrim(char *, char *); 867 | char *strmrplc(char *, char *, char *); 868 | char *strocat(char *, char *); 869 | char *strrpt(char *, char *, size_t); 870 | char *strrjust(char *, size_t); 871 | char *strrplc(char * , char *, char *); 872 | char *strrtrim(char * , char *); 873 | char *strtrim(char *, char *); 874 | char *strvcat(char *, char *, ...); 875 | 876 | 877 | 878 | /*********************************************************************/ 879 | /* */ 880 | /* Bulletin Generator declarations */ 881 | /* */ 882 | /*********************************************************************/ 883 | 884 | typedef MDSP_BOOL (*ParseBltnFnPtr) ( char *bltn, 885 | char **rptPtr, 886 | char *bbbTypePtr, 887 | char **prefixPtr, 888 | short *YYPtr, 889 | short *GGPtr, 890 | char *bltnTypePtr, 891 | char **headingPtr ); 892 | 893 | void cbltngen ( ParseBltnFnPtr fnPtr, 894 | char *filename, 895 | Devaddr *historyDevice, 896 | Diskaddr *historyAddr, 897 | unsigned * bltnInCountPtr, 898 | unsigned * bltnOutCountPtr, 899 | unsigned * rptOutCountPtr ); 900 | 901 | void tbltngen ( ParseBltnFnPtr fnPtr, 902 | char *filename, 903 | Devaddr *historyDevice, 904 | Diskaddr *historyAddr, 905 | unsigned * bltnInCountPtr, 906 | unsigned * bltnOutCountPtr, 907 | unsigned * rptOutCountPtr ); 908 | 909 | typedef MDSP_BOOL (*ParseBltnFnPtrX) ( char *bltn, 910 | char **rptPtr, 911 | char *bbbTypePtr, 912 | char **prefixPtr, 913 | short *YYPtr, 914 | short *GGPtr, 915 | short *ggPtr, 916 | char *bltnTypePtr, 917 | char **headingPtr ); 918 | 919 | void xbltngen ( ParseBltnFnPtrX fnPtr, 920 | char *filename, 921 | Devaddr *historyDevice, 922 | Diskaddr *historyAddr, 923 | unsigned * bltnInCountPtr, 924 | unsigned * bltnOutCountPtr, 925 | unsigned * rptOutCountPtr ); 926 | 927 | void dbltngen ( ParseBltnFnPtrX fnPtr, 928 | char *filename, 929 | Devaddr *historyDevice, 930 | Diskaddr *historyAddr, 931 | unsigned * bltnInCountPtr, 932 | unsigned * bltnOutCountPtr, 933 | unsigned * rptOutCountPtr ); 934 | 935 | typedef MDSP_BOOL (*OParseBltnFnPtr) ( char *bltn, 936 | char **rptPtr, 937 | char *bbbTypePtr, 938 | char **prefixPtr, 939 | short *YYPtr, 940 | short *GGPtr, 941 | char *bltnTypePtr, 942 | char **headingPtr, 943 | char **ccccPtr ); 944 | 945 | void obltngen ( OParseBltnFnPtr fnPtr, 946 | char *filename, 947 | Devaddr *historyDevice, 948 | Diskaddr *historyAddr, 949 | unsigned * bltnInCountPtr, 950 | unsigned * bltnOutCountPtr, 951 | unsigned * rptOutCountPtr ); 952 | 953 | 954 | void pbltngen ( OParseBltnFnPtr fnPtr, 955 | char *filename, 956 | Devaddr *historyDevice, 957 | Diskaddr *historyAddr, 958 | unsigned * bltnInCountPtr, 959 | unsigned * bltnOutCountPtr, 960 | unsigned * rptOutCountPtr ); 961 | 962 | 963 | void sbltngen ( OParseBltnFnPtr fnPtr, 964 | char *filename, 965 | Devaddr *historyDevice, 966 | Diskaddr *historyAddr, 967 | unsigned * bltnInCountPtr, 968 | unsigned * bltnOutCountPtr, 969 | unsigned * rptOutCountPtr ); 970 | 971 | 972 | void ebltngen ( ParseBltnFnPtr fnPtr, 973 | char *filename, 974 | Devaddr *historyDevice, 975 | Diskaddr *historyAddr, 976 | unsigned * bltnInCountPtr, 977 | unsigned * bltnOutCountPtr, 978 | unsigned * rptOutCountPtr ); 979 | 980 | 981 | /*********************************************************************/ 982 | /* */ 983 | /* Typedefs and function prototypes for retrieving information from */ 984 | /* switching directory. */ 985 | /* */ 986 | /*********************************************************************/ 987 | 988 | typedef struct sw_dir_info_rec { 989 | char wmo_header[11]; 990 | char AFOS_pil[10]; 991 | char multiple_line; 992 | short int line_num; 993 | short int recvd_line; 994 | char flag1; 995 | char flag2; 996 | char flag3; 997 | //char class; 998 | short int domestic_cat_num; 999 | char afos_tmp; 1000 | char ccb[2]; 1001 | char region_addr; 1002 | short int output_line_count; 1003 | unsigned short trans_line[128]; 1004 | char change_date[3]; 1005 | char dir_flags; 1006 | Diskaddr history_file_addr; 1007 | char birth_date[3]; 1008 | } SwDirInfo; 1009 | 1010 | 1011 | SwDirInfo *rtswdir(char *, int); 1012 | SwDirInfo *rtpswdir(void); 1013 | SwDirInfo *rtnswdir(void); 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | /*********************************************************************/ 1020 | /* */ 1021 | /* General local functions */ 1022 | /* */ 1023 | /*********************************************************************/ 1024 | 1025 | 1026 | int itoc(int, char *, int); 1027 | 1028 | int antoi(char *, int); 1029 | 1030 | float antof(char *, int); 1031 | 1032 | void errmsg(char *, ...); 1033 | 1034 | void logmsg(char *, ...); 1035 | 1036 | void opermsg(char *, ...); 1037 | 1038 | int lmsg(const char *, const char *, ...); 1039 | int emsg(const char *, const char *, ...); 1040 | int omsg(const char *, const char *, ...); 1041 | 1042 | void ASCTOEB(char *, int); 1043 | 1044 | void EAXLATE(char *, int); 1045 | 1046 | void PASCTOEB(char *, int); 1047 | 1048 | char **bldhdarr(char *); 1049 | 1050 | void dalchdar(char **); 1051 | 1052 | void *CCAPREAD(char *, int); 1053 | 1054 | void CCAPWRIT(char *, char *, int); 1055 | 1056 | int PPTOI(char); 1057 | 1058 | char itopp(int); 1059 | 1060 | int diffmin(int, int, int, int, int, int); 1061 | 1062 | char incrseq(char); 1063 | 1064 | void nextdate(int *, int *, int *); 1065 | 1066 | void prevdate(int *, int *, int *); 1067 | 1068 | void rdstaddr(char *, char *); 1069 | 1070 | int wrenaddr(char *, char *); 1071 | 1072 | int vfydigit (char *, int); 1073 | 1074 | int readline(char * , int); 1075 | 1076 | int prevjul(int, int); 1077 | 1078 | int nextjul(int, int); 1079 | 1080 | int fcomppos(fpos_t *, fpos_t *); 1081 | 1082 | void lfprint(char *); 1083 | 1084 | void flfprint(FILE *, char *); 1085 | 1086 | void slfprint(char *, int, char *); 1087 | 1088 | void flfnprnt(FILE *, char *, int); 1089 | 1090 | void slfnprnt(char *, int, char *, int); 1091 | 1092 | int strhash(char *); 1093 | 1094 | void reverse(char *); 1095 | 1096 | #ifndef _WIN32 1097 | MDSP_BOOL itoa(int, char *, int); 1098 | #endif 1099 | 1100 | int getsnn(char * , int); 1101 | 1102 | int fgetsnn(char *, int, FILE *); 1103 | 1104 | int getreply(char *, char *, int); 1105 | 1106 | MDSP_BOOL strfit(char *, char *, size_t); 1107 | 1108 | MDSP_BOOL addrfrm3(char *, Diskaddr *); 1109 | 1110 | MDSP_BOOL addrfrm5(char *, Diskaddr *); 1111 | 1112 | MDSP_BOOL addrto3(Diskaddr *, char *); 1113 | 1114 | MDSP_BOOL addrto5(Diskaddr *, char *); 1115 | 1116 | int addrcmp(Diskaddr *, Diskaddr *); 1117 | 1118 | void incraddr(Diskaddr *, Diskaddr *, Diskaddr *); 1119 | void decraddr(Diskaddr *, Diskaddr *, Diskaddr *); 1120 | 1121 | char *readrec(Diskaddr *, Devaddr *, int, void *); 1122 | 1123 | int writerec(Diskaddr*, Devaddr *, int, void *); 1124 | 1125 | char prhold(char *, ...); 1126 | 1127 | void dump(char *, int); 1128 | 1129 | void fdump(FILE *, char *, int); 1130 | 1131 | void fwdump(FILE *, char *, int); 1132 | 1133 | /* char toascii(char); */ 1134 | 1135 | char *strtoas(char *); 1136 | 1137 | char *strntoas(char *, int); 1138 | 1139 | char toebcdic(char); 1140 | 1141 | char *strtoeb(char *); 1142 | 1143 | char *strntoeb(char *, int); 1144 | 1145 | #ifndef _WIN32 1146 | char *lfind(char *, char *, int, int, int(*)(char *, char *)); 1147 | char *lsearch(char *, char *, int *, int, int(*)(char *, char *)); 1148 | #endif 1149 | 1150 | MDSP_BOOL strcmpw(char *, char *); 1151 | 1152 | int strccnt(char *, int); 1153 | 1154 | int strnccnt(char *, int, size_t); 1155 | 1156 | int pprt(FILE *, char *, char *, char *, char *, ...); 1157 | 1158 | MDSP_BOOL pprtbrk(FILE *, char *, char *, char *); 1159 | 1160 | MDSP_BOOL pprtend(FILE *, char *); 1161 | 1162 | MDSP_BOOL pprtinit(int, char, char *, char *, char *); 1163 | 1164 | char *monthnam(int, char); 1165 | 1166 | char *getrec(FILE *, int, char *); 1167 | 1168 | MDSP_BOOL jtog(int, int, int *, int *, int *); 1169 | 1170 | MDSP_BOOL gtoj(int, int, int, int *, int *); 1171 | 1172 | MDSP_BOOL ccap2std(char *, Devaddr *, Diskaddr *); 1173 | 1174 | MDSP_BOOL std2ccap(Devaddr *, Diskaddr *, char *); 1175 | 1176 | char *rptstrip(char *); 1177 | char *rptstrp2(char *); 1178 | char *rptfmt(char *); 1179 | char *rptfmt2(char *); 1180 | char *rptfmti(char *, unsigned short int); 1181 | char *rptfmtni(char *, unsigned short int); 1182 | 1183 | // char *strnstr(char *, char *, size_t); 1184 | 1185 | int stregion(int); 1186 | int ccregion(char *); 1187 | char *rgnname(int); 1188 | 1189 | // void *memrchr(const void *, int, size_t); 1190 | 1191 | MDSP_BOOL sysmonms(char *, char *, ...); 1192 | MDSP_BOOL sysmoncl(char *); 1193 | 1194 | short prevndx ( short max, short min, short current ); 1195 | short nextndx ( short max, short min, short current ); 1196 | 1197 | time_t extrym ( unsigned day, unsigned hour, unsigned minute ); 1198 | time_t extrymd ( unsigned hour, unsigned minute ); 1199 | 1200 | int cmptimet ( time_t t1, time_t t2 ); 1201 | 1202 | int tfprintf ( FILE *, const char *, ... ); 1203 | 1204 | MDSP_BOOL purgelog ( char *filename, unsigned short delete_age ); 1205 | 1206 | time_t odbtime ( void ); 1207 | 1208 | int bltnpcnt ( char *, int ); 1209 | void bltnpage ( char *, int, int ); 1210 | 1211 | int HEXTOI( char *, int ); 1212 | 1213 | char **hdgxref( char * ); 1214 | 1215 | struct tm *zonetime( unsigned short, unsigned short, char ); 1216 | 1217 | int wordcnt( char * ); 1218 | int wordcntn( char *, unsigned int ); 1219 | 1220 | char *word( char *, unsigned int ); 1221 | char *wordn( char *, unsigned int, unsigned int ); 1222 | 1223 | char *crlfstrp( char * ); 1224 | 1225 | MDSP_BOOL charcmp( char *, char * ); 1226 | 1227 | int linecnt( char * ); 1228 | int linecntn( char *, unsigned int ); 1229 | 1230 | char *bltline( char *, unsigned int ); 1231 | char *bltlinen( char *, unsigned int, unsigned int ); 1232 | 1233 | char *pttoline( char *, unsigned int ); 1234 | char *pttoword( char *, unsigned int ); 1235 | 1236 | char *moblrgn(unsigned short, 1237 | unsigned short, 1238 | unsigned short ); 1239 | 1240 | char *nxtgroup( char * ); 1241 | 1242 | void prtmdade(struct MDAD_data *); 1243 | 1244 | #endif 1245 | -------------------------------------------------------------------------------- /src/metar_structs.h: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef METARX 21 | #define METARX 22 | 23 | #include "../include/metar.h" 24 | 25 | #include "local.h" /* standard header file */ 26 | 27 | #define MAXWXSYMBOLS 10 /*-- NOT TO EXCEED 10 PRES. WX GRPS --*/ 28 | #define MAXTOKENS 500 /*-- RPT NOT TO EXCEED 500 GRPS --*/ 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/metar_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "metar_structs.h" 21 | #ifdef SYNOPTIC 22 | 23 | char *BldSynop( Decoded_METAR * , char * ); 24 | /*char *Sec0MeSm(Decoded_METAR *);*/ 25 | /*char *Sec1MeSm(Decoded_METAR *, char *);*/ 26 | /*char *Sec3MeSm(Decoded_METAR *, char *);*/ 27 | /*char *Sec5MeSm(Decoded_METAR *, char *);*/ 28 | #endif 29 | 30 | void print_decoded_metar( Decoded_METAR *); 31 | int decode_metar( const char *, Decoded_METAR * ); 32 | 33 | int runTest() { 34 | Decoded_METAR Metar; 35 | Decoded_METAR *Mptr = &Metar; 36 | int ErReturn; 37 | char *input1 = "KVBG 120955Z 00000KT 1/4 FG VV001 13/13 A2994 RMK AO2A"; 38 | if ( (ErReturn = decode_metar( input1, Mptr )) != 0 ) { 39 | printf("Failed to decode %s", input1); 40 | return 0; 41 | } 42 | if (strcmp(Mptr->stnid,"KVBG") != 0) { 43 | printf("Wrong station id (%s) for metar %s", Mptr->stnid, input1); 44 | return 0; 45 | } 46 | if (Mptr->ob_date != 12) { 47 | printf("Wrong observation date (%d) for metar %s", Mptr->ob_date, input1); 48 | return 0; 49 | } 50 | if (Mptr->ob_hour != 9) { 51 | printf("Wrong observation hour (%d) for metar %s", Mptr->ob_hour, input1); 52 | return 0; 53 | } 54 | if (Mptr->ob_minute != 55) { 55 | printf("Wrong observation minute (%d) for metar %s", Mptr->ob_minute, input1); 56 | return 0; 57 | } 58 | if (Mptr->AUTO != FALSE) { 59 | printf("Wrong auto indication (%d) for metar %s", Mptr->AUTO, input1); 60 | return 0; 61 | } 62 | if (Mptr->winData.windDir != 0) { 63 | printf("Wrong observation wind direction (%d) for metar %s", Mptr->winData.windDir, input1); 64 | return 0; 65 | } 66 | if (Mptr->winData.windSpeed != 0) { 67 | printf("Wrong observation wind speed (%d) for metar %s", Mptr->winData.windSpeed, input1); 68 | return 0; 69 | } 70 | if (strcmp(Mptr->winData.windUnits, "KT") != 0) { 71 | printf("Wrong observation wind units (%s) for metar %s", Mptr->winData.windUnits, input1); 72 | return 0; 73 | } 74 | if (Mptr->prevail_vsbySM != 0.25) { 75 | printf("Wrong observation visibility (%f) for metar %s", Mptr->prevail_vsbySM, input1); 76 | return 0; 77 | } 78 | if (strcmp(Mptr->WxObstruct[0], "FG") != 0) { 79 | printf("Wrong observation obscuration (%s) for metar %s", Mptr->WxObstruct[0], input1); 80 | return 0; 81 | } 82 | if (Mptr->VertVsby != 30) { 83 | printf("Wrong observation vertical visibility (%d) for metar %s", Mptr->VertVsby, input1); 84 | return 0; 85 | } 86 | if (Mptr->dew_pt_temp != 13) { 87 | printf("Wrong observation dew point (%d) for metar %s", Mptr->dew_pt_temp, input1); 88 | return 0; 89 | } 90 | if (Mptr->temp != 13) { 91 | printf("Wrong observation temp (%d) for metar %s", Mptr->temp, input1); 92 | return 0; 93 | } 94 | if (Mptr->inches_altstng != 29.94) { 95 | printf("Wrong observation altimeter (%f) for metar %s", Mptr->inches_altstng, input1); 96 | return 0; 97 | } 98 | if (strcmp(Mptr->autoIndicator, "A02A") != 0) { 99 | printf("Wrong observation remark auto indicator (%s) for metar %s", Mptr->autoIndicator, input1); 100 | return 0; 101 | } 102 | return 1; 103 | } 104 | 105 | /********************************************************************/ 106 | /* */ 107 | /* Title: dRVMETAR */ 108 | /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */ 109 | /* Date: 28 Oct 1994 */ 110 | /* Programmer: CARL MCCALLA */ 111 | /* Language: C/370 */ 112 | /* */ 113 | /* Abstract: DRVMETAR is a main routine that acts a driver */ 114 | /* for testing the METAR Decoder function. */ 115 | /* */ 116 | /* External Functions Called: */ 117 | /* None. */ 118 | /* decode_metar */ 119 | /* print_decoded_metar */ 120 | /* Sec0MTSm */ 121 | /* Sec1MTSm */ 122 | /* */ 123 | /* Input: None */ 124 | /* */ 125 | /* Output: None */ 126 | /* */ 127 | /* Modification History: */ 128 | /* None. */ 129 | /* */ 130 | /********************************************************************/ 131 | int main() 132 | { 133 | runTest(); 134 | 135 | static char *string[] = 136 | { 137 | "KVBG 120955Z 00000KT 1/4 FG VV001 13/13 A2994 RMK AO2A", 138 | "KNFW 072252Z 34015G21KT 10SM CLR 25/03 A3010 RMK AO2 PK WND 34029/2156 SLP176 T02500033 CHINO N VISNO N $", 139 | "KBIL 101707Z 02012KT 3SM UP BR SCT002 BKN008 OVC029 00/M01 A3008 RMK AO2 UPB07SNE07 P0001 $", 140 | "KFOD 072355Z AUTO 00000KT 10SM CLR 11/07 A2996 RMK AO2 60003 10130 20100 402100100 57003 PWINO FZRANO RVRNO", 141 | 142 | "KRNO 101655Z 36010KT 10SM SCT050 BKN070 OVC100 03/M07 A2994 RMK AO2 SLP134 VCSH MTNS OBSCD SW-NW T00331067", 143 | 144 | "KMKG 18022G29KT 3SM BR BKN018 BR 24/22 A2995 RMK A02 VIS 2", 145 | 146 | 147 | "KPIT 132351Z 33013KT 4SM +TSRA BR BKN018CB OVC031 12/11 A2977 RMK " 148 | "AO2 PK WND 31041/2305 WSHFT 2300 PRESSRR SLP090 FRQ LTGCGCC OHD " 149 | "TS OHD MOV E CB OHD MOV E 8/3// P0051 60052 T01170111 10222 20122 " 150 | "53030", 151 | 152 | 153 | "KCAK 132351Z 28016G22KT 10SM BKN021 OVC030 11/09 A2981 RMK AO2 " 154 | "TSE00RAE10 PRESRR SLP093 TS MOV NE CIG RGD 8/5// P0002 60066 " 155 | "T01110094 10217 20111 51053", 156 | 157 | "KBUF 132354Z 21007KT 3SM +TSRA BR FEW009 OVC 12/11 A2959 RMK " 158 | "AO2 PRESFR SLP021 8/9// TS ALQDS MOV E OCNL LTGICCCCG P0031 " 159 | "60073 T01170111 10233 20111 50000 0", 160 | 161 | 162 | "KPIT 132356Z 32012G21KT 4SM TSRA BR BKN018CB OVC031 12/11 A2978 " 163 | "RMK AO2 WSHFT 2338 PRESFR FRQ LTGCGCC OHD TS OHD MOV E CB OHD MOV " 164 | "E P0001", 165 | 166 | 167 | "KCAK 132358Z 28015G22KT 10SM BKN013 OVC023 11/10 A2982 RMK AO2", 168 | 169 | "KBUF 140001Z 22008KT 3SM +TSRA BR BKN009 BKN013 OVC022 12/12 A2959 " 170 | "RMK AO2 P0003", 171 | 172 | 173 | 174 | "KRIL 031853Z AUTO 33008KT 10SM SCT022 BKN032 OVC060 07/01 A3004 " 175 | "RMK AO2 SLP157 T00720006 TSNO", 176 | 177 | 178 | "METAR KCLE 091657Z COR 35021KT 3SM -PL SHPL VV004 M03/M04 A2964 " 179 | "RMK VIS S M1/4=", 180 | 181 | "METAR KCLE 091657Z COR 35021KT 3SM -PE SHPE VV004 M03/M04 A2964 " 182 | "RMK VIS S M1/4=", 183 | 184 | "METAR KCLE 091657Z COR 35021KT 3SM -PE TSPL VV004 M03/M04 A2964 " 185 | "RMK VIS S M1/4=", 186 | 187 | "METAR KCLE 091657Z COR 35021KT 3SM -PL TSPE VV004 M03/M04 A2964 " 188 | "RMK VIS S M1/4=", 189 | 190 | 191 | "KMLB 200450Z 18006KT 7SM OVC100 23/22 A2986 RMK FQT LTGIG W-N", 192 | 193 | "KMLB 200450Z 18006KT 7SM OVC100 23/22 A2986 RMK FQT LTGIG W-N=", 194 | 195 | "KMLB 200450Z 18006KT 7SM OVC100 23/22 A2986 RMK FRQ LTGIC NW", 196 | 197 | "KMLB 200450Z 18006KT 7SM OVC100 23/22 A2986 RMK FRQ LTGCC NW=", 198 | 199 | 200 | "SPECI KEKO 151609Z 00000KT 5SM BR FEW003 SCT013 M04/M06 A3018 " 201 | "RMK VIS N-NE M1/4", 202 | 203 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 204 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/MM A2992", 205 | 206 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 207 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/M12 A2992", 208 | 209 | "METAR KLAX 281156Z AUTO VRB100G135KT 130V210 3 9999 " 210 | "R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC " 211 | "+TS VCTS FEW/// SCT000 BKN050 SCT150 OVC250 3/M1 A2991 RMK " 212 | "TORNADO B13 DSNT NE A01 PK WND 18515/45 " 213 | "WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 " 214 | "VIS 2 1/2 RWY11 " 215 | "DVR/1000V1600FT " 216 | "SHRAB05E30SHSNB20E55 FZDZB1057E1059 CIG 1000V1500 CIG 020 RWY11 " 217 | "PRESFR PRESRR SLP013 FG FEW/// HZ SCT000 VIS NW 2 1/2 GR 3/4 " 218 | "VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC " 219 | "FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 " 220 | "933125 98096 P0125 60225 70565 " 221 | "T00261015 10369 21026 " 222 | "404800360 52101 VISNO RWY05 CHINO RWY27 PNO RVRNO " 223 | "PWINO FZRANO TSNO $", 224 | 225 | 226 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 227 | "RMK SLP046 ESTMD SLP VIS SW-NW 2 " 228 | "PWINO FZRANO TSNO $", 229 | 230 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 231 | "RMK SLP046 ESTMD SLP VIS SW-NW 2 1/2 " 232 | "PWINO FZRANO TSNO $", 233 | 234 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 235 | "RMK SLP046 ESTMD SLP VIS SW-NW 2", 236 | 237 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 238 | "RMK SLP046 ESTMD SLP VIS SW-NW 2 1/2=", 239 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 240 | "RMK SLP046 ESTMD SLP VIS SW-NW 2", 241 | 242 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 243 | "RMK CIG 003V026 SLP046 ESTMD SLP VIS SW-NW 2", 244 | 245 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 246 | "RMK VIS S 2", 247 | 248 | "SPECI KEKO 151609Z 00000KT 5SM BR FEW003 SCT013 M04/M06 A3018 " 249 | "RMK VIS N-NE 1", 250 | 251 | 252 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 253 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/MM A2992", 254 | 255 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 256 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/M12 A2992", 257 | 258 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 259 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/MM A2992", 260 | 261 | 262 | 263 | 264 | 265 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 266 | "RMK CIG 003V026 SLP046 ESTMD SLP VIS SW-NW 2=", 267 | 268 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 269 | "RMK VIS S 2=", 270 | 271 | "SPECI KEKO 151609Z 00000KT 5SM BR FEW003 SCT013 M04/M06 A3018 " 272 | "RMK VIS N-NE 1=", 273 | 274 | 275 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 276 | "RMK SLP046 ESTMD SLP VIS SW-NW 2", 277 | 278 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 279 | "RMK CIG 003V026 SLP046 ESTMD SLP VIS SW-NW 2", 280 | 281 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 282 | "RMK VIS S 2", 283 | 284 | "SPECI KEKO 151609Z 00000KT 5SM BR FEW003 SCT013 M04/M06 A3018 " 285 | "RMK VIS N-NE 1", 286 | 287 | 288 | 289 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 290 | "RMK SLP046 ESTMD SLP VIS SW 2", 291 | 292 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 293 | "RMK CIG 003V026 SLP046 ESTMD SLP VIS NW 2", 294 | 295 | "METAR KAFF 091657Z COR 35021KT 3SM -SG BR VV004 M03/M04 A2964 " 296 | "RMK VIS S 2", 297 | 298 | "SPECI KEKO 151609Z 00000KT 5SM BR FEW003 SCT013 M04/M06 A3018 " 299 | "RMK VIS NE 1", 300 | 301 | 302 | "KPIT 1935Z 22015G25KT 1/8SM R22L/2700FT " 303 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/12 A2992", 304 | 305 | "KPIT 1935Z 22015G25KT 6SM R22L/2700FT " 306 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M12/M18 A2992", 307 | 308 | "KPIT 1935Z 22015G25KT 8SM R22L/2700FT " 309 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/12 A2992", 310 | 311 | "KPIT 1935Z 22015G25KT 9SM R22L/2700FT " 312 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/M01 A2992", 313 | 314 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 315 | "TSRA -DZ FG +SNPE SCT005TCU BKN010ACSL OVC250CB MM/12 A2992", 316 | 317 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 318 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/MM A2992", 319 | 320 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 321 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/M12 A2992", 322 | 323 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 324 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/MM A2992", 325 | 326 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 327 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/MM A2992", 328 | 329 | "SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 " 330 | "A2900 RMK A02A PK WND 18056/28 OCNL LTG AP " 331 | "RAB15E25TSB20 FCB1430 PRESFR " 332 | "SLP 701 P 0254 T01990182", 333 | 334 | 335 | "METAR KLAX 281156Z AUTO VRB100G135KT 130V210 3 9999 " 336 | "R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC " 337 | "+TS VCTS FEW/// SCT000 BKN050 SCT150 OVC250 3/M1 A2991 RMK " 338 | "TORNADO B13 DSNT NE A01 PK WND 18515/45 " 339 | "WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 " 340 | "VIS 2 1/2 RWY11 " 341 | "DVR/1000V1600FT " 342 | "SHRAB05E30SHSNB20E55 FZDZB1057E1059 CIG 1000V1500 CIG 020 RWY11 " 343 | "PRESFR PRESRR SLP013 FG FEW/// HZ SCT000 VIS NW 2 1/2 GR 3/4 " 344 | "VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC " 345 | "FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 " 346 | "933125 98096 P0125 60225 70565 " 347 | "T00261015 10369 21026 " 348 | "404800360 52101 VISNO RWY05 CHINO RWY27 PNO RVRNO " 349 | "PWINO FZRANO TSNO $", 350 | 351 | "KP88 1919Z 09001KT 14/03 RMK AO / PKWND 002/RNO 158 Z T01440034", 352 | 353 | "K40B 1924Z 29004KT 15/M07 RMK AO PKWND 011/RM MV263 T01501072", 354 | 355 | 356 | 357 | "SPECI KGFI 041430Z COR 18045G56KT " 358 | "M1/4SM R15/0200FT R01L/0600V1000FT R01L/M0600FT R27/P6000FT " 359 | "+FC +TS -FZDZ VV010 04/M02 " 360 | "A2900 RMK TORNADO B13 6 NE A02A PK WND 18056/28 WSHFT 30 FROPA " 361 | "TWR VIS 1 1/2 VIS NE 2 1/2 VIS 2 1/2 RWY11 DVR/0600V1000FT " 362 | "OCNL LTGICCG OVHD RAB15E25 TSB20 FCB1430 TS SE MOV NE GR 1 3/4 " 363 | "VIRGA SW CIG 005V010 FG SCT000 BKN014 V OVC CB DSNT W " 364 | "CIG 002 RWY11 PRESFR PRESRR " 365 | "SLP701 ACFT MSHP NOSPECI SNINCR 2/10 FIRST " 366 | "P0254 60217 70125 4/021 933036 8/903 98096 T00261015 " 367 | "11021 21001 401120084 52032RVRNO PWINO PNO FZRANO TSNO " 368 | "VISNO RWY06 CHINO RWY12 $", 369 | 370 | 371 | 372 | "KPHX 281156Z 12004KT 16KM CLR 15/05 A2996 RMK AOA SLP135 T01500050 " 373 | "10250 20150 53006", 374 | "KFCA 281156Z 30003KT 10SM CLR 06/02 A3009 RMRK AO TNO $ SLP191 " 375 | "T00610023 10167 20056 53003", 376 | "KAST 281156Z 00000KT 10SM BKN095 09/08 A2997 REMARK AOA SLP150 " 377 | "T00940084 10161 20094 52005 ", 378 | "KHVR 281156Z 03003KT 10SM OVC020 09/07 A3010 REMARKS AO TNO ZRNO " 379 | "$ SLP194 T00940073 10156 20089 51005", 380 | 381 | "KGGW 281156Z 35006KT 5SM BR OVC010 10/09 A3003 RMK AOA $ SLP177 " 382 | "70003 T01000095 10156 20110 53008", 383 | "KELY 1153Z AUTO 14004KT 10SM SCT075 01/M01 A3011 RMK AOA TNO ZRNO " 384 | "SLP171 70001 T00061011 10139 21006 51005", 385 | "KFLG 281156Z 29006KT 10SM CLR 04/M01 A3012 RMK AO TNO SLP147 " 386 | "T00391011 21006 51004", 387 | "KGTF 281156Z 27005KT 7SM BKN080 04/04 A3010 RMK AOA SLP205 " 388 | "T00440045 10117 20039 51006", 389 | "KHLN 281156Z AUTO 27005KT 10SM OVC023 07/05 A3011 RMK AOA OVC V " 390 | "BKN $ SLP202 60000 70001 T00670050 10122 20061 53003", 391 | 392 | "K13A 1918Z 20011KT 26/M06 RMK AO PKWND 020/RNO 644V264 T02611061", 393 | 394 | 395 | "KGGW 1756Z 33018KT 10SM OVC015 M03/M06 A3041 RMK AOA SLP338 " 396 | "4/007 60002 T10281055 11028 21072 51009", 397 | "KPHX 1756Z 130004KT 10SM CLR 18/M03 A3001 RMK AOA SLP154 " 398 | "T01781033 10178 20067 58007", 399 | "KFCA 1756Z 29005KT 10SM CLR 05/M11 A3049 RMK AOA TNO SLP352 " 400 | "T00501111 10050 21044 50004", 401 | "KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 " 402 | "T01110045 10111 20000 50002", 403 | "KHVR 1756Z 31007KT 5SM -SN SCT011 BKN024 OVC030 M05/M08 A3056 " 404 | "RMK AOA 933004 " 405 | "BKN V SCT TNO P0000 $ SLP389 4/015 60002 " 406 | "T10501077 11050 21078 51010", 407 | "KELY 1753Z 34010KT 10SM CLR 01/M07 A3022 RMK AOA TNO FZRNO " 408 | "SLP240 T00111066 10011 21078 58007", 409 | "KFLG 1756Z 07006KT 10SM CLR 06/M12 A3009 RMK AO TNO FZRNO " 410 | "SLP178 T00561122 10061 21100 58005", 411 | "KGTF 1756Z 35010KT 1/2SM -SN FG VV09 M06/M08 A3051 RMK AOA " 412 | "933004 SFC VSBY 3/4 " 413 | "P0009 SLP393 60010 T10611077 11044 21067 53013", 414 | "KHLN 1756Z 35012KT 10SM SCT032 OVC060 M02/M09 A3048 RMK AOA " 415 | "SLP369 60000 T10171094 11017 21061 53006", 416 | "KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 61104 " 417 | "71235 T01110045 10111 20000 401720056 58002", 418 | "METAR KLAX 04281156Z AUTO VRB100G135KT 130V210 3 1/2SM " 419 | "R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC " 420 | "+TS BLPY FEW000 BKN050 SCT150 OVC250 3/M1 A2991 RMK " 421 | "TORNADO B13 DSNT NE A02 PK WND 18515/45 " 422 | "WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 " 423 | "VIS 2 1/2 RWY11 OCNL LTG VCY STN " 424 | "RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RWY11 " 425 | "PRESFR PRESRR SLP013 FG FEW000 VIS NW2 1/2 GR 3/4 " 426 | "VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC " 427 | "FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 " 428 | "933125 98096 P0125 60225 70565 " 429 | "T00261015 10369 21026 " 430 | "404800360 52101 PWINO FZRANO TSNO $", 431 | 432 | 433 | 434 | "METAR KGFI 041356Z AUTO 17012KT 130V210 3 1/2SM R15L/0500FT -RA " 435 | "SCT050 OVC110 26/18 A2991 RMK FUNNEL CLOUDS A02 RAB30 " 436 | "SLP 101 GR M1/4 VIRGA SCT V BKN P 0010 T02640178", 437 | 438 | "METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 " 439 | "RMK WATERSPOUTS VCY STN NW A02 SLP 101 10288 20243 52021 $ ", 440 | 441 | "SPECI KGFI 041420Z AUTO 18030KT 3 1/2SM RVRNO TS -RA BKN008 OVC060 " 442 | "26/22 A2991 RMK A02 RA15TSB20 PRESFR SLP 101 P 0000 T02640218", 443 | 444 | "KABE 281900Z NIL", 445 | 446 | "METAR KPIT NIL", 447 | 448 | "METAR KCLE 04281156Z 170100G135KT 110V180 M1/4SM " 449 | "R01L/P6000FT +TSSHRA VCFG " 450 | "BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 " 451 | "WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 " 452 | "CIG 1000V1500 PRESFR FRQ LTG CG NW " 453 | "RAB1030E1145 FZDZE56 PRESRR SLP135 GS " 454 | "T1263 " 455 | "VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 " 456 | "404800360 52101 PWINO FZRANO TSNO $", 457 | 458 | "METAR KPHL 040256Z AUTO 170100G135KT 130V210 1/2SM " 459 | "R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT " 460 | "FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 " 461 | "WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 LTG DSNT " 462 | "RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP037 GR 2 3/4 " 463 | "VIRGA E 8/365 4/178 P 0125 70565 21026 T0263 10369 60225 " 464 | "404800360 52101 PWINO FZRANO TSNO $", 465 | 466 | "SPECI KGFI 041420Z AUTO 18030KT 2 1/2SM RVRNO TS -RA BKN008 " 467 | "OVC060 25/22 A2991 RMK A02 LTG DSNT W " 468 | "RAB15TSB20 PRESFR SLP101 P 0000 " 469 | "254/218", 470 | 471 | "METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM " 472 | "R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT " 473 | "FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 " 474 | "WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 " 475 | "RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR M1/4 " 476 | "VIRGA SE 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 " 477 | "404800360 52101 PWINO FZRANO TSNO $", 478 | 479 | 480 | 481 | "METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM " 482 | "R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT " 483 | "FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 " 484 | "WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 " 485 | "RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 " 486 | "VIRGA 35 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 " 487 | "VIRGA 35 8/365 4/178 P 0125 21026 70565 10369 60225 T0263 21026 " 488 | "404800360 52101 PWINO FZRANO TSNO $", 489 | 490 | 491 | "METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM " 492 | "R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT " 493 | "FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 18515/45 " 494 | "WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 " 495 | "RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 " 496 | "VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 " 497 | "404800360 52101 PWINO FZRANO TSNO $", 498 | 499 | "METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM " 500 | "R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT " 501 | "FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 185150/1345 " 502 | "WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 " 503 | "RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 " 504 | "VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 " 505 | "404800360 52101 PWINO FZRANO TSNO", 506 | 507 | 508 | 509 | "METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 RMK " 510 | "A02 SLP 101 10288 20243 52021", 511 | "SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 " 512 | "M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR " 513 | "SLP 701 P 0254 M199/M182", 514 | 515 | "SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 " 516 | "M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR " 517 | "SLP 701 P 0254 M199/182", 518 | 519 | "SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 " 520 | "M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR " 521 | "SLP 701 P 0254 199/M182", 522 | 523 | "METAR APIT 171755Z AUTO 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 524 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 525 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 526 | "RMK 4/369 58033 6003/ TWELVE 70125 10039 20029 410840112 " 527 | "PCPN 0009 8/563 WSHFT 1715 PK WND 2032/1725 " 528 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 529 | "SFC VIS 1 1/2 VIS 1 1/2V2 SLP875 SGB1213E1225", 530 | 531 | "NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 " 532 | " Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK SLP056 " 533 | "RAE0123", 534 | 535 | "SPECI APIT 171755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 536 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 537 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 538 | "RMK 58033 6003/ TWELVE 70125 8/321 10039 20029 410840112 " 539 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 540 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 541 | "SFC VIS 1 1/2 VIS 1 SLP875 FGB1713", 542 | 543 | "APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 544 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 545 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 546 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 547 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 548 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 549 | "SFC VIS 1 1/2 VIS 1V2 SLP875", 550 | 551 | 552 | "APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 553 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 554 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 555 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 556 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 557 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 558 | "SFC VIS 1 1/2 VIS 1 1/2V2 1/2 SLP875", 559 | 560 | "APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 561 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 562 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 563 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 564 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 565 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 566 | "SFC VIS 1 1/2 VIS 1V2 1/2 SLP875", 567 | 568 | 569 | "EGPF 1720Z 00000KT 9999 -SHRA STC014 SCT020CB BNK024 12/09 " 570 | "Q1003 NOSIG", 571 | 572 | "NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG", 573 | "NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 " 574 | " Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT", 575 | "DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015", 576 | "DAAT 1830Z 30010KT CAVOK 29/06 Q1019", 577 | 578 | "GQPP 1800Z 34023KT 3000 DRSA SKC 24/20 Q1011 NSG", 579 | "DAAG 1830Z 06006KT 9999 SCT020 25/22 Q1015", 580 | "DABB 1830Z 04010KT 9999 SCT030TCU SCT033CB 27/18 Q1017", 581 | "DABC 1830Z 00000KT 9999 SCT026TCU SCT036CB 22/18 Q1020 RETS", 582 | 583 | "NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG", 584 | "NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 " 585 | " Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK K", 586 | "NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 " 587 | " Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT", 588 | "DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015", 589 | 590 | "GFLL 1900Z NIL", 591 | 592 | "GOOY 1800Z 03006G17KT 340V080 6000 TSRA BKN016 BKN030CB " 593 | "BKN133 26/23 Q1013 NOSIG", 594 | 595 | "GCXO 1930Z 32018KT 8000 SCT003 SCT007 18/16 Q1019", 596 | 597 | "APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 598 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 599 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 600 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 601 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 602 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 603 | "SFC VIS 1 1/2 VIS 1 1/2V2", 604 | 605 | "BPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 606 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 607 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 608 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 609 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 610 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 611 | "SFC VIS 1 1/2 VIS 1V2", 612 | 613 | "CPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 614 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 615 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 616 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 617 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 618 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 619 | "SFC VIS 1 1/2 VIS 1V2 1/2", 620 | 621 | "DPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 622 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 623 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 624 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 625 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 626 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 627 | "SFC VIS 1 1/2 VIS 1 1/2V2 1/2", 628 | 629 | "EPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 630 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 631 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 632 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 633 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 634 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 635 | "SFC VIS 1 1/2 VIS 1/2V3/4", 636 | 637 | "FPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 638 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 639 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 640 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 641 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 642 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 643 | "SFC VIS 1 1/2 VIS 3/4V2 1/2", 644 | 645 | "GPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT " 646 | "R34/1000V1600FT R01L/P6000FT R04RR/900FT " 647 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 " 648 | "RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 " 649 | "PCPN 0009 WSHFT 1715 PK WND 2032/1725 " 650 | "CIG 20V25 WND 12V25 TWR VIS 2 1/2 " 651 | "SFC VIS 1 1/2 VIS 3/4V3", 652 | 653 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 654 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/M16 A2992", 655 | 656 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 657 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/16 A2992", 658 | 659 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 660 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/M16 A2992", 661 | 662 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 663 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/M16 A2992", 664 | 665 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 666 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/16 A2992", 667 | 668 | "KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT " 669 | "TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/MM A2992", 670 | 671 | "YBPN 212100Z AUTO 15004KT 9999 // SCT093 OVC110 25/22 Q1014", 672 | 673 | "EGLL 212250Z AUTO 23013KT 9999 BKN016 12/09 Q1012 NOSIG", 674 | 675 | "YBPN 172200Z AUTO 17008KT 9999 // BKN034 BKN042 28/23 Q1014", 676 | 677 | "YBPN 172200Z AUTO 17008KT //// // BKN034 BKN042 28/23 Q1014", 678 | 679 | "EHAM 191455Z 11007KT 070V220 CAVOK 24/11 Q1006 NOSIG", 680 | 681 | "KMMU 251746Z 35009 10SM SCT050 OVC065 09/M01 A3023", 682 | 683 | "UUEE 251746Z 35009 10SM SCT050 OVC065 09/M01 A3023", 684 | 685 | "CWLI 220200Z AUTO ///// M1/4SM //// OVC007 M27/M30 A3017", 686 | 687 | "CWLI 220200Z AUTO ///// M1/4SM //// ////// M27/M30 A3017", 688 | 689 | "CWYK 230500Z AUTO ///// M15/ A2946 RMK SLP049", 690 | 691 | "KMMU 251746Z 35009MPS 10SM SCT050 OVC065 09/M01 A3023", 692 | 693 | "LSZB 010250Z AUTO 16003KT 0200 R14/0175N FG VV001 01/01 Q0999", 694 | 695 | "SAME 100100Z 32004KT 9999 SCT030 SCT04022/17 Q1020", 696 | 697 | NULL}; 698 | 699 | Decoded_METAR Metar; 700 | Decoded_METAR *Mptr = &Metar; 701 | int j, 702 | ErReturn; 703 | static char *synopRTRN = NULL; 704 | char bltn_prefix[20]; 705 | 706 | j = 0; 707 | 708 | while( string[j] != NULL) 709 | { 710 | /*-- PRINT INPUT METAR REPORT ----------------------------*/ 711 | printf("\n\nINPUT METAR REPORT:\n\n %s\n\n",string[j] ); 712 | 713 | /*-- DECODE INPUT REPORT ---------------------------------*/ 714 | if ( (ErReturn = decode_metar( string[ j ], Mptr )) != 0 ) 715 | printf("decode_metar: Error Return Number: %d\n",ErReturn); 716 | 717 | /*-- PRINT DECODED METAR REPORT ELEMENTS -----------------*/ 718 | printf("\n\nFINAL DECODED PRODUCT...\n\n"); 719 | print_decoded_metar( Mptr ); 720 | j++; 721 | 722 | } 723 | return 0; 724 | } 725 | 726 | // vim: set ts=4 sw=4 sts=4 noet : 727 | -------------------------------------------------------------------------------- /src/print_decoded_metar.c: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "metar_structs.h" 21 | 22 | char* distance_as_string(Distance_Unit unit) { 23 | switch (unit) { 24 | case DIST_FEET: return "FT"; 25 | case DIST_METERS: return "M"; 26 | default: return "UNKNOWN UNIT"; 27 | } 28 | } 29 | 30 | /* NB this is pretty insecure insofar as it blindly writes into string 31 | * on the assuption that outstring can fit it all 32 | * */ 33 | 34 | void sprintf_tornadic_info (char * outstring, Decoded_METAR *Mptr) { 35 | char temp[100]; 36 | 37 | if ( Mptr->TornadicType[0] != '\0' ) { 38 | sprintf(temp, "TORNADIC ACTVTY TYPE: %s\n", 39 | Mptr->TornadicType ); 40 | strcat(outstring, temp); 41 | } 42 | 43 | if ( Mptr->BTornadicHour != MAXINT ) { 44 | sprintf(temp, "TORN. ACTVTY BEGHOUR: %d\n", 45 | Mptr->BTornadicHour ); 46 | strcat(outstring, temp); 47 | } 48 | 49 | if ( Mptr->BTornadicMinute != MAXINT ) { 50 | sprintf(temp, "TORN. ACTVTY BEGMIN : %d\n", 51 | Mptr->BTornadicMinute ); 52 | strcat(outstring, temp); 53 | } 54 | 55 | if ( Mptr->ETornadicHour != MAXINT ) { 56 | sprintf(temp, "TORN. ACTVTY ENDHOUR: %d\n", 57 | Mptr->ETornadicHour ); 58 | strcat(outstring, temp); 59 | } 60 | 61 | if ( Mptr->ETornadicMinute != MAXINT ) { 62 | sprintf(temp, "TORN. ACTVTY ENDMIN : %d\n", 63 | Mptr->ETornadicMinute ); 64 | strcat(outstring, temp); 65 | } 66 | 67 | if ( Mptr->TornadicDistance != MAXINT ) { 68 | sprintf(temp, "TORN. DIST. FROM STN: %d\n", 69 | Mptr->TornadicDistance ); 70 | strcat(outstring, temp); 71 | } 72 | 73 | if ( Mptr->TornadicLOC[0] != '\0' ) { 74 | sprintf(temp, "TORNADIC LOCATION : %s\n", 75 | Mptr->TornadicLOC ); 76 | strcat(outstring, temp); 77 | } 78 | 79 | if ( Mptr->TornadicDIR[0] != '\0' ) { 80 | sprintf(temp, "TORNAD. DIR FROM STN: %s\n", 81 | Mptr->TornadicDIR ); 82 | strcat(outstring, temp); 83 | } 84 | 85 | if ( Mptr->TornadicMovDir[0] != '\0' ) { 86 | sprintf(temp, "TORNADO DIR OF MOVM.: %s\n", 87 | Mptr->TornadicMovDir ); 88 | strcat(outstring, temp); 89 | } 90 | } 91 | 92 | 93 | /* NB this is pretty insecure insofar as it blindly writes into string 94 | * on the assuption that outstring can fit it all 95 | * */ 96 | 97 | void sprint_metar (char * outstring, Decoded_METAR *Mptr) 98 | { 99 | int i; 100 | char temp[100]; 101 | 102 | sprintf(outstring, "\n\n\n/*******************************************/\n"); 103 | strcat(outstring, "/* THE DECODED METAR REPORT FOLLOWS */\n"); 104 | strcat(outstring, "/*******************************************/\n\n"); 105 | 106 | if ( Mptr->codeName[ 0 ] != '\0' ) { 107 | sprintf(temp, "REPORT CODE NAME : %s\n",Mptr->codeName); 108 | strcat(outstring, temp); 109 | } 110 | 111 | if ( Mptr->stnid[ 0 ] != '\0' ) { 112 | sprintf(temp, "STATION ID : %s\n",Mptr->stnid); 113 | strcat(outstring, temp); 114 | } 115 | 116 | if ( Mptr->ob_date != MAXINT ) { 117 | sprintf(temp, "OBSERVATION DAY : %d\n",Mptr->ob_date); 118 | strcat(outstring, temp); 119 | } 120 | 121 | if ( Mptr->ob_hour != MAXINT ) { 122 | sprintf(temp, "OBSERVATION HOUR : %d\n",Mptr->ob_hour); 123 | strcat(outstring, temp); 124 | } 125 | 126 | if ( Mptr->ob_minute != MAXINT ) { 127 | sprintf(temp, "OBSERVATION MINUTE : %d\n",Mptr->ob_minute); 128 | strcat(outstring, temp); 129 | } 130 | 131 | if ( Mptr->NIL_rpt ) { 132 | sprintf(temp, "NIL REPORT : TRUE\n"); 133 | strcat(outstring, temp); 134 | } 135 | 136 | if ( Mptr->AUTO ) { 137 | sprintf(temp, "AUTO REPORT : TRUE\n"); 138 | strcat(outstring, temp); 139 | } 140 | 141 | if ( Mptr->COR ) { 142 | sprintf(temp, "CORRECTED REPORT : TRUE\n"); 143 | strcat(outstring, temp); 144 | } 145 | 146 | if ( Mptr->winData.windVRB ) { 147 | sprintf(temp, "WIND DIRECTION VRB : TRUE\n"); 148 | strcat(outstring, temp); 149 | } 150 | 151 | if ( Mptr->winData.windDir != MAXINT ) { 152 | sprintf(temp, "WIND DIRECTION : %d\n",Mptr->winData.windDir); 153 | strcat(outstring, temp); 154 | } 155 | 156 | if ( Mptr->winData.windSpeed != MAXINT ) { 157 | sprintf(temp, "WIND SPEED : %d\n",Mptr->winData.windSpeed); 158 | strcat(outstring, temp); 159 | } 160 | 161 | if ( Mptr->winData.windGust != MAXINT ) { 162 | sprintf(temp, "WIND GUST : %d\n",Mptr->winData.windGust); 163 | strcat(outstring, temp); 164 | } 165 | 166 | if ( Mptr->winData.windUnits[ 0 ] != '\0' ) { 167 | sprintf(temp, "WIND UNITS : %s\n",Mptr->winData.windUnits); 168 | strcat(outstring, temp); 169 | } 170 | 171 | if ( Mptr->minWnDir != MAXINT ) { 172 | sprintf(temp, "MIN WIND DIRECTION : %d\n",Mptr->minWnDir); 173 | strcat(outstring, temp); 174 | } 175 | 176 | if ( Mptr->maxWnDir != MAXINT ) { 177 | sprintf(temp, "MAX WIND DIRECTION : %d\n",Mptr->maxWnDir); 178 | strcat(outstring, temp); 179 | } 180 | 181 | if ( Mptr->prevail_vsbyM != (float) MAXINT ) { 182 | sprintf(temp, "PREVAIL VSBY (M) : %f\n",Mptr->prevail_vsbyM); 183 | strcat(outstring, temp); 184 | } 185 | 186 | if ( Mptr->prevail_vsbyKM != (float) MAXINT ) { 187 | sprintf(temp, "PREVAIL VSBY (KM) : %f\n",Mptr->prevail_vsbyKM); 188 | strcat(outstring, temp); 189 | } 190 | 191 | if ( Mptr->prevail_vsbySM != (float) MAXINT ) { 192 | sprintf(temp, "PREVAIL VSBY (SM) : %.3f\n",Mptr->prevail_vsbySM); 193 | strcat(outstring, temp); 194 | } 195 | 196 | if ( Mptr->vsby_Dir[ 0 ] != '\0' ) { 197 | sprintf(temp, "VISIBILITY DIRECTION: %s\n",Mptr->vsby_Dir); 198 | strcat(outstring, temp); 199 | } 200 | 201 | if ( Mptr->RVRNO ) { 202 | sprintf(temp, "RVRNO : TRUE\n"); 203 | strcat(outstring, temp); 204 | } 205 | 206 | for ( i = 0; i < MAX_RUNWAYS; i++ ) 207 | { 208 | if( Mptr->RRVR[i].runway_designator[0] != '\0' ) { 209 | sprintf(temp, "RUNWAY DESIGNATOR : %s\n", 210 | Mptr->RRVR[i].runway_designator); 211 | strcat(outstring, temp); 212 | } 213 | 214 | if( Mptr->RRVR[i].visRange != MAXINT ) { 215 | sprintf(temp, "R_WAY VIS RANGE (%s): %d\n", 216 | distance_as_string(Mptr->RRVR[i].distance_unit), 217 | Mptr->RRVR[i].visRange); 218 | strcat(outstring, temp); 219 | } 220 | 221 | if ( Mptr->RRVR[i].vrbl_visRange ) { 222 | sprintf(temp, "VRBL VISUAL RANGE : TRUE\n"); 223 | strcat(outstring, temp); 224 | } 225 | 226 | if ( Mptr->RRVR[i].below_min_RVR ) { 227 | sprintf(temp, "BELOW MIN RVR : TRUE\n"); 228 | strcat(outstring, temp); 229 | } 230 | 231 | if ( Mptr->RRVR[i].above_max_RVR ) { 232 | sprintf(temp, "ABOVE MAX RVR : TRUE\n"); 233 | strcat(outstring, temp); 234 | } 235 | 236 | if( Mptr->RRVR[i].Max_visRange != MAXINT ) { 237 | sprintf(temp, "MX R_WAY VISRNG (%s): %d\n", 238 | distance_as_string(Mptr->RRVR[i].distance_unit), 239 | Mptr->RRVR[i].Max_visRange); 240 | strcat(outstring, temp); 241 | } 242 | 243 | if( Mptr->RRVR[i].Min_visRange != MAXINT ) { 244 | sprintf(temp, "MN R_WAY VISRNG (%s): %d\n", 245 | distance_as_string(Mptr->RRVR[i].distance_unit), 246 | Mptr->RRVR[i].Min_visRange); 247 | strcat(outstring, temp); 248 | } 249 | 250 | } 251 | 252 | 253 | if( Mptr->DVR.visRange != MAXINT ) { 254 | sprintf(temp, "DISPATCH VIS RANGE : %d\n", 255 | Mptr->DVR.visRange); 256 | strcat(outstring, temp); 257 | } 258 | 259 | if ( Mptr->DVR.vrbl_visRange ) { 260 | sprintf(temp, "VRBL DISPATCH VISRNG: TRUE\n"); 261 | strcat(outstring, temp); 262 | } 263 | 264 | if ( Mptr->DVR.below_min_DVR ) { 265 | sprintf(temp, "BELOW MIN DVR : TRUE\n"); 266 | strcat(outstring, temp); 267 | } 268 | 269 | if ( Mptr->DVR.above_max_DVR ) { 270 | sprintf(temp, "ABOVE MAX DVR : TRUE\n"); 271 | strcat(outstring, temp); 272 | } 273 | 274 | if( Mptr->DVR.Max_visRange != MAXINT ) { 275 | sprintf(temp, "MX DSPAT VISRNG (FT): %d\n", 276 | Mptr->DVR.Max_visRange); 277 | strcat(outstring, temp); 278 | } 279 | 280 | if( Mptr->DVR.Min_visRange != MAXINT ) { 281 | sprintf(temp, "MN DSPAT VISRNG (FT): %d\n", 282 | Mptr->DVR.Min_visRange); 283 | strcat(outstring, temp); 284 | } 285 | 286 | for (i = 0; Mptr->WxObstruct[i][0] != '\0' && i < MAXWXSYMBOLS; i++) 287 | { 288 | sprintf(temp, "WX/OBSTRUCT VISION : %s\n", 289 | Mptr->WxObstruct[i] ); 290 | strcat(outstring, temp); 291 | } 292 | 293 | for (i = 0; i < MAX_PARTIAL_OBSCURATIONS; i++) { 294 | if ( Mptr->PartialObscurationAmt[i][0] != '\0' ) { 295 | sprintf(temp, "OBSCURATION AMOUNT : %s\n", 296 | Mptr->PartialObscurationAmt[i]); 297 | strcat(outstring, temp); 298 | } 299 | 300 | if ( Mptr->PartialObscurationPhenom[i][0] != '\0' ) { 301 | sprintf(temp, "OBSCURATION PHENOM : %s\n", 302 | Mptr->PartialObscurationPhenom[i]); 303 | strcat(outstring, temp); 304 | } 305 | } 306 | 307 | for (i = 0; Mptr->cloudGroup[ i ].cloud_type[0] != '\0' && 308 | i < MAX_CLOUD_GROUPS; i++ ) 309 | { 310 | if ( Mptr->cloudGroup[ i ].cloud_type[0] != '\0' ) { 311 | sprintf(temp, "CLOUD COVER : %s\n", 312 | Mptr->cloudGroup[ i ].cloud_type); 313 | strcat(outstring, temp); 314 | } 315 | 316 | if ( Mptr->cloudGroup[ i ].cloud_hgt_char[0] != '\0' ) { 317 | sprintf(temp, "CLOUD HGT (CHARAC.) : %s\n", 318 | Mptr->cloudGroup[ i ].cloud_hgt_char); 319 | strcat(outstring, temp); 320 | } 321 | 322 | if ( Mptr->cloudGroup[ i ].cloud_hgt_meters != MAXINT) { 323 | sprintf(temp, "CLOUD HGT (METERS) : %d\n", 324 | Mptr->cloudGroup[ i ].cloud_hgt_meters); 325 | strcat(outstring, temp); 326 | } 327 | 328 | if ( Mptr->cloudGroup[ i ].other_cld_phenom[0] != '\0' ) { 329 | sprintf(temp, "OTHER CLOUD PHENOM : %s\n", 330 | Mptr->cloudGroup[ i ].other_cld_phenom); 331 | strcat(outstring, temp); 332 | } 333 | } 334 | 335 | if ( Mptr->temp != MAXINT ) { 336 | sprintf(temp, "TEMP. (CELSIUS) : %d\n", Mptr->temp); 337 | strcat(outstring, temp); 338 | } 339 | 340 | if ( Mptr->dew_pt_temp != MAXINT ) { 341 | sprintf(temp, "D.P. TEMP. (CELSIUS): %d\n", Mptr->dew_pt_temp); 342 | strcat(outstring, temp); 343 | } 344 | 345 | if ( Mptr->A_altstng ) { 346 | sprintf(temp, "ALTIMETER (INCHES) : %.2f\n", 347 | Mptr->inches_altstng ); 348 | strcat(outstring, temp); 349 | } 350 | 351 | if ( Mptr->Q_altstng ) { 352 | sprintf(temp, "ALTIMETER (PASCALS) : %d\n", 353 | Mptr->hectoPasc_altstng ); 354 | strcat(outstring, temp); 355 | } 356 | 357 | sprintf_tornadic_info (outstring, Mptr); 358 | 359 | if ( Mptr->autoIndicator[0] != '\0' ) { 360 | sprintf(temp, "AUTO INDICATOR : %s\n", 361 | Mptr->autoIndicator); 362 | strcat(outstring, temp); 363 | } 364 | 365 | if ( Mptr->PKWND_dir != MAXINT ) { 366 | sprintf(temp, "PEAK WIND DIRECTION : %d\n",Mptr->PKWND_dir); 367 | strcat(outstring, temp); 368 | } 369 | if ( Mptr->PKWND_speed != MAXINT ) { 370 | sprintf(temp, "PEAK WIND SPEED : %d\n",Mptr->PKWND_speed); 371 | strcat(outstring, temp); 372 | } 373 | if ( Mptr->PKWND_hour != MAXINT ) { 374 | sprintf(temp, "PEAK WIND HOUR : %d\n",Mptr->PKWND_hour); 375 | strcat(outstring, temp); 376 | } 377 | if ( Mptr->PKWND_minute != MAXINT ) { 378 | sprintf(temp, "PEAK WIND MINUTE : %d\n",Mptr->PKWND_minute); 379 | strcat(outstring, temp); 380 | } 381 | 382 | if ( Mptr->WshfTime_hour != MAXINT ) { 383 | sprintf(temp, "HOUR OF WIND SHIFT : %d\n",Mptr->WshfTime_hour); 384 | strcat(outstring, temp); 385 | } 386 | if ( Mptr->WshfTime_minute != MAXINT ) { 387 | sprintf(temp, "MINUTE OF WIND SHIFT: %d\n",Mptr->WshfTime_minute); 388 | strcat(outstring, temp); 389 | } 390 | if ( Mptr->Wshft_FROPA != FALSE ) { 391 | sprintf(temp, "FROPA ASSOC. W/WSHFT: TRUE\n"); 392 | strcat(outstring, temp); 393 | } 394 | 395 | if ( Mptr->TWR_VSBY != (float) MAXINT ) { 396 | sprintf(temp, "TOWER VISIBILITY : %.2f\n",Mptr->TWR_VSBY); 397 | strcat(outstring, temp); 398 | } 399 | if ( Mptr->SFC_VSBY != (float) MAXINT ) { 400 | sprintf(temp, "SURFACE VISIBILITY : %.2f\n",Mptr->SFC_VSBY); 401 | strcat(outstring, temp); 402 | } 403 | 404 | if ( Mptr->minVsby != (float) MAXINT ) { 405 | sprintf(temp, "MIN VRBL_VIS (SM) : %.4f\n",Mptr->minVsby); 406 | strcat(outstring, temp); 407 | } 408 | if ( Mptr->maxVsby != (float) MAXINT ) { 409 | sprintf(temp, "MAX VRBL_VIS (SM) : %.4f\n",Mptr->maxVsby); 410 | strcat(outstring, temp); 411 | } 412 | 413 | if( Mptr->VSBY_2ndSite != (float) MAXINT ) { 414 | sprintf(temp, "VSBY_2ndSite (SM) : %.4f\n",Mptr->VSBY_2ndSite); 415 | strcat(outstring, temp); 416 | } 417 | 418 | if( Mptr->VSBY_2ndSite_LOC[0] != '\0' ) { 419 | sprintf(temp, "VSBY_2ndSite LOC. : %s\n", 420 | Mptr->VSBY_2ndSite_LOC); 421 | strcat(outstring, temp); 422 | } 423 | 424 | if ( Mptr->OCNL_LTG ) { 425 | sprintf(temp, "OCCASSIONAL LTG : TRUE\n"); 426 | strcat(outstring, temp); 427 | } 428 | 429 | if ( Mptr->FRQ_LTG ) { 430 | sprintf(temp, "FREQUENT LIGHTNING : TRUE\n"); 431 | strcat(outstring, temp); 432 | } 433 | 434 | if ( Mptr->CNS_LTG ) { 435 | sprintf(temp, "CONTINUOUS LTG : TRUE\n"); 436 | strcat(outstring, temp); 437 | } 438 | 439 | if ( Mptr->CG_LTG ) { 440 | sprintf(temp, "CLOUD-GROUND LTG : TRUE\n"); 441 | strcat(outstring, temp); 442 | } 443 | 444 | if ( Mptr->IC_LTG ) { 445 | sprintf(temp, "IN-CLOUD LIGHTNING : TRUE\n"); 446 | strcat(outstring, temp); 447 | } 448 | 449 | if ( Mptr->CC_LTG ) { 450 | sprintf(temp, "CLD-CLD LIGHTNING : TRUE\n"); 451 | strcat(outstring, temp); 452 | } 453 | 454 | if ( Mptr->CA_LTG ) { 455 | sprintf(temp, "CLOUD-AIR LIGHTNING : TRUE\n"); 456 | strcat(outstring, temp); 457 | } 458 | 459 | if ( Mptr->AP_LTG ) { 460 | sprintf(temp, "LIGHTNING AT AIRPORT: TRUE\n"); 461 | strcat(outstring, temp); 462 | } 463 | 464 | if ( Mptr->OVHD_LTG ) { 465 | sprintf(temp, "LIGHTNING OVERHEAD : TRUE\n"); 466 | strcat(outstring, temp); 467 | } 468 | 469 | if ( Mptr->DSNT_LTG ) { 470 | sprintf(temp, "DISTANT LIGHTNING : TRUE\n"); 471 | strcat(outstring, temp); 472 | } 473 | 474 | if ( Mptr->LightningVCTS ) { 475 | sprintf(temp, "L'NING W/I 5-10(ALP): TRUE\n"); 476 | strcat(outstring, temp); 477 | } 478 | 479 | if ( Mptr->LightningTS ) { 480 | sprintf(temp, "L'NING W/I 5 (ALP) : TRUE\n"); 481 | strcat(outstring, temp); 482 | } 483 | 484 | if ( Mptr->VcyStn_LTG ) { 485 | sprintf(temp, "VCY STN LIGHTNING : TRUE\n"); 486 | strcat(outstring, temp); 487 | } 488 | 489 | if ( Mptr->LTG_DIR[0] != '\0' ) { 490 | sprintf(temp, "DIREC. OF LIGHTNING : %s\n", Mptr->LTG_DIR); 491 | strcat(outstring, temp); 492 | } 493 | 494 | 495 | 496 | i = 0; 497 | while( i < 3 && Mptr->ReWx[ i ].Recent_weather[0] != '\0' ) 498 | { 499 | sprintf(temp, "RECENT WEATHER : %s", 500 | Mptr->ReWx[i].Recent_weather); 501 | strcat(outstring, temp); 502 | 503 | if ( Mptr->ReWx[i].Bhh != MAXINT ) { 504 | sprintf(temp, " BEG_hh = %d",Mptr->ReWx[i].Bhh); 505 | strcat(outstring, temp); 506 | } 507 | if ( Mptr->ReWx[i].Bmm != MAXINT ) { 508 | sprintf(temp, " BEG_mm = %d",Mptr->ReWx[i].Bmm); 509 | strcat(outstring, temp); 510 | } 511 | 512 | if ( Mptr->ReWx[i].Ehh != MAXINT ) { 513 | sprintf(temp, " END_hh = %d",Mptr->ReWx[i].Ehh); 514 | strcat(outstring, temp); 515 | } 516 | if ( Mptr->ReWx[i].Emm != MAXINT ) { 517 | sprintf(temp, " END_mm = %d",Mptr->ReWx[i].Emm); 518 | strcat(outstring, temp); 519 | } 520 | 521 | strcat(outstring, "\n"); 522 | 523 | i++; 524 | } 525 | 526 | if ( Mptr->minCeiling != MAXINT ) { 527 | sprintf(temp, "MIN VRBL_CIG (FT) : %d\n",Mptr->minCeiling); 528 | strcat(outstring, temp); 529 | } 530 | if ( Mptr->maxCeiling != MAXINT ) { 531 | sprintf(temp, "MAX VRBL_CIG (FT)) : %d\n",Mptr->maxCeiling); 532 | strcat(outstring, temp); 533 | } 534 | 535 | if ( Mptr->CIG_2ndSite_Meters != MAXINT ) { 536 | sprintf(temp, "CIG2ndSite (FT) : %d\n",Mptr->CIG_2ndSite_Meters); 537 | strcat(outstring, temp); 538 | } 539 | if ( Mptr->CIG_2ndSite_LOC[0] != '\0' ) { 540 | sprintf(temp, "CIG @ 2nd Site LOC. : %s\n",Mptr->CIG_2ndSite_LOC); 541 | strcat(outstring, temp); 542 | } 543 | 544 | if ( Mptr->PRESFR ) { 545 | sprintf(temp, "PRESFR : TRUE\n"); 546 | strcat(outstring, temp); 547 | } 548 | if ( Mptr->PRESRR ) { 549 | sprintf(temp, "PRESRR : TRUE\n"); 550 | strcat(outstring, temp); 551 | } 552 | 553 | if ( Mptr->SLPNO ) { 554 | sprintf(temp, "SLPNO : TRUE\n"); 555 | strcat(outstring, temp); 556 | } 557 | 558 | if ( Mptr->SLP != (float) MAXINT ) { 559 | sprintf(temp, "SLP (hPa) : %.1f\n", Mptr->SLP); 560 | strcat(outstring, temp); 561 | } 562 | 563 | if ( Mptr->SectorVsby != (float) MAXINT ) { 564 | sprintf(temp, "SECTOR VSBY (MILES) : %.2f\n", Mptr->SectorVsby ); 565 | strcat(outstring, temp); 566 | } 567 | 568 | if ( Mptr->SectorVsby_Dir[ 0 ] != '\0' ) { 569 | sprintf(temp, "SECTOR VSBY OCTANT : %s\n", Mptr->SectorVsby_Dir ); 570 | strcat(outstring, temp); 571 | } 572 | 573 | if ( Mptr->TS_LOC[ 0 ] != '\0' ) { 574 | sprintf(temp, "THUNDERSTORM LOCAT. : %s\n", Mptr->TS_LOC ); 575 | strcat(outstring, temp); 576 | } 577 | 578 | if ( Mptr->TS_MOVMNT[ 0 ] != '\0' ) { 579 | sprintf(temp, "THUNDERSTORM MOVMNT.: %s\n", Mptr->TS_MOVMNT); 580 | strcat(outstring, temp); 581 | } 582 | 583 | if ( Mptr->GR ) { 584 | sprintf(temp, "GR (HAILSTONES) : TRUE\n"); 585 | strcat(outstring, temp); 586 | } 587 | 588 | if ( Mptr->GR_Size != (float) MAXINT ) { 589 | sprintf(temp, "HLSTO SIZE (INCHES) : %.3f\n",Mptr->GR_Size); 590 | strcat(outstring, temp); 591 | } 592 | 593 | if ( Mptr->VIRGA ) { 594 | sprintf(temp, "VIRGA : TRUE\n"); 595 | strcat(outstring, temp); 596 | } 597 | 598 | if ( Mptr->VIRGA_DIR[0] != '\0' ) { 599 | sprintf(temp, "DIR OF VIRGA FRM STN: %s\n", Mptr->VIRGA_DIR); 600 | strcat(outstring, temp); 601 | } 602 | 603 | for( i = 0; i < MAX_SURFACE_OBSCURATIONS; i++ ) { 604 | if( Mptr->SfcObscuration[i][0] != '\0' ) { 605 | sprintf(temp, "SfcObscuration : %s\n", 606 | Mptr->SfcObscuration[i]); 607 | strcat(outstring, temp); 608 | } 609 | } 610 | 611 | if ( Mptr->Num8thsSkyObscured != MAXINT ) { 612 | sprintf(temp, "8ths of SkyObscured : %d\n",Mptr->Num8thsSkyObscured); 613 | strcat(outstring, temp); 614 | } 615 | 616 | if ( Mptr->CIGNO ) { 617 | sprintf(temp, "CIGNO : TRUE\n"); 618 | strcat(outstring, temp); 619 | } 620 | 621 | if ( Mptr->Ceiling != MAXINT ) { 622 | sprintf(temp, "Ceiling (ft) : %d\n",Mptr->Ceiling); 623 | strcat(outstring, temp); 624 | } 625 | 626 | if ( Mptr->Estimated_Ceiling != MAXINT ) { 627 | sprintf(temp, "Estimated CIG (ft) : %d\n",Mptr->Estimated_Ceiling); 628 | strcat(outstring, temp); 629 | } 630 | 631 | if ( Mptr->VrbSkyBelow[0] != '\0' ) { 632 | sprintf(temp, "VRB SKY COND BELOW : %s\n",Mptr->VrbSkyBelow); 633 | strcat(outstring, temp); 634 | } 635 | 636 | if ( Mptr->VrbSkyAbove[0] != '\0' ) { 637 | sprintf(temp, "VRB SKY COND ABOVE : %s\n",Mptr->VrbSkyAbove); 638 | strcat(outstring, temp); 639 | } 640 | 641 | if ( Mptr->VrbSkyLayerHgt != MAXINT ) { 642 | sprintf(temp, "VRBSKY COND HGT (FT): %d\n",Mptr->VrbSkyLayerHgt); 643 | strcat(outstring, temp); 644 | } 645 | 646 | if ( Mptr->ObscurAloftHgt != MAXINT ) { 647 | sprintf(temp, "Hgt Obscur Aloft(ft): %d\n",Mptr->ObscurAloftHgt); 648 | strcat(outstring, temp); 649 | } 650 | 651 | if ( Mptr->ObscurAloft[0] != '\0' ) { 652 | sprintf(temp, "Obscur Phenom Aloft : %s\n",Mptr->ObscurAloft); 653 | strcat(outstring, temp); 654 | } 655 | 656 | if ( Mptr->ObscurAloftSkyCond[0] != '\0' ) { 657 | sprintf(temp, "Obscur ALOFT SKYCOND: %s\n",Mptr->ObscurAloftSkyCond); 658 | strcat(outstring, temp); 659 | } 660 | 661 | 662 | if ( Mptr->NOSPECI ) { 663 | sprintf(temp, "NOSPECI : TRUE\n"); 664 | strcat(outstring, temp); 665 | } 666 | 667 | if ( Mptr->LAST ) { 668 | sprintf(temp, "LAST : TRUE\n"); 669 | strcat(outstring, temp); 670 | } 671 | 672 | if ( Mptr->synoptic_cloud_type[ 0 ] != '\0' ) { 673 | sprintf(temp, "SYNOPTIC CLOUD GROUP: %s\n",Mptr->synoptic_cloud_type); 674 | strcat(outstring, temp); 675 | } 676 | 677 | if ( Mptr->CloudLow != '\0' ) { 678 | sprintf(temp, "LOW CLOUD CODE : %c\n",Mptr->CloudLow); 679 | strcat(outstring, temp); 680 | } 681 | 682 | if ( Mptr->CloudMedium != '\0' ) { 683 | sprintf(temp, "MEDIUM CLOUD CODE : %c\n",Mptr->CloudMedium); 684 | strcat(outstring, temp); 685 | } 686 | 687 | if ( Mptr->CloudHigh != '\0' ) { 688 | sprintf(temp, "HIGH CLOUD CODE : %c\n",Mptr->CloudHigh); 689 | strcat(outstring, temp); 690 | } 691 | 692 | if ( Mptr->SNINCR != MAXINT ) { 693 | sprintf(temp, "SNINCR (INCHES) : %d\n",Mptr->SNINCR); 694 | strcat(outstring, temp); 695 | } 696 | 697 | if ( Mptr->SNINCR_TotalDepth != MAXINT ) { 698 | sprintf(temp, "SNINCR(TOT. INCHES) : %d\n",Mptr->SNINCR_TotalDepth); 699 | strcat(outstring, temp); 700 | } 701 | 702 | if ( Mptr->snow_depth_group[ 0 ] != '\0' ) { 703 | sprintf(temp, "SNOW DEPTH GROUP : %s\n",Mptr->snow_depth_group); 704 | strcat(outstring, temp); 705 | } 706 | 707 | if ( Mptr->snow_depth != MAXINT ) { 708 | sprintf(temp, "SNOW DEPTH (INCHES) : %d\n",Mptr->snow_depth); 709 | strcat(outstring, temp); 710 | } 711 | 712 | if ( Mptr->WaterEquivSnow != (float) MAXINT ) { 713 | sprintf(temp, "H2O EquivSno(inches): %.2f\n",Mptr->WaterEquivSnow); 714 | strcat(outstring, temp); 715 | } 716 | 717 | if ( Mptr->SunshineDur != MAXINT ) { 718 | sprintf(temp, "SUNSHINE (MINUTES) : %d\n",Mptr->SunshineDur); 719 | strcat(outstring, temp); 720 | } 721 | 722 | if ( Mptr->SunSensorOut ) { 723 | sprintf(temp, "SUN SENSOR OUT : TRUE\n"); 724 | strcat(outstring, temp); 725 | } 726 | 727 | if ( Mptr->hourlyPrecip != (float) MAXINT ) { 728 | sprintf(temp, "HRLY PRECIP (INCHES): %.2f\n",Mptr->hourlyPrecip); 729 | strcat(outstring, temp); 730 | } 731 | 732 | if( Mptr->precip_amt != (float) MAXINT) { 733 | sprintf(temp, "3/6HR PRCIP (INCHES): %.2f\n", 734 | Mptr->precip_amt); 735 | strcat(outstring, temp); 736 | } 737 | 738 | if( Mptr->Indeterminant3_6HrPrecip ) { 739 | sprintf(temp, "INDTRMN 3/6HR PRECIP: TRUE\n"); 740 | strcat(outstring, temp); 741 | } 742 | 743 | if( Mptr->precip_24_amt != (float) MAXINT) { 744 | sprintf(temp, "24HR PRECIP (INCHES): %.2f\n", 745 | Mptr->precip_24_amt); 746 | strcat(outstring, temp); 747 | } 748 | 749 | if ( Mptr->Indeterminant_24HrPrecip ) { 750 | sprintf(temp, "INDTRMN 24 HR PRECIP: TRUE\n"); 751 | strcat(outstring, temp); 752 | } 753 | 754 | if ( Mptr->Temp_2_tenths != (float) MAXINT ) { 755 | sprintf(temp, "TMP2TENTHS (CELSIUS): %.1f\n",Mptr->Temp_2_tenths); 756 | strcat(outstring, temp); 757 | } 758 | 759 | if ( Mptr->DP_Temp_2_tenths != (float) MAXINT ) { 760 | sprintf(temp, "DPT2TENTHS (CELSIUS): %.1f\n",Mptr->DP_Temp_2_tenths); 761 | strcat(outstring, temp); 762 | } 763 | 764 | if ( Mptr->maxtemp != (float) MAXINT) { 765 | sprintf(temp, "MAX TEMP (CELSIUS) : %.1f\n", 766 | Mptr->maxtemp); 767 | strcat(outstring, temp); 768 | } 769 | 770 | if ( Mptr->mintemp != (float) MAXINT) { 771 | sprintf(temp, "MIN TEMP (CELSIUS) : %.1f\n", 772 | Mptr->mintemp); 773 | strcat(outstring, temp); 774 | } 775 | 776 | if ( Mptr->max24temp != (float) MAXINT) { 777 | sprintf(temp, "24HrMAXTMP (CELSIUS): %.1f\n", 778 | Mptr->max24temp); 779 | strcat(outstring, temp); 780 | } 781 | 782 | if ( Mptr->min24temp != (float) MAXINT) { 783 | sprintf(temp, "24HrMINTMP (CELSIUS): %.1f\n", 784 | Mptr->min24temp); 785 | strcat(outstring, temp); 786 | } 787 | 788 | if ( Mptr->char_prestndcy != MAXINT) { 789 | sprintf(temp, "CHAR PRESS TENDENCY : %d\n", 790 | Mptr->char_prestndcy ); 791 | strcat(outstring, temp); 792 | } 793 | 794 | if ( Mptr->prestndcy != (float) MAXINT) { 795 | sprintf(temp, "PRES. TENDENCY (hPa): %.1f\n", 796 | Mptr->prestndcy ); 797 | strcat(outstring, temp); 798 | } 799 | 800 | if ( Mptr->PWINO ) { 801 | sprintf(temp, "PWINO : TRUE\n"); 802 | strcat(outstring, temp); 803 | } 804 | 805 | if ( Mptr->PNO ) { 806 | sprintf(temp, "PNO : TRUE\n"); 807 | strcat(outstring, temp); 808 | } 809 | 810 | if ( Mptr->CHINO ) { 811 | sprintf(temp, "CHINO : TRUE\n"); 812 | strcat(outstring, temp); 813 | } 814 | 815 | if ( Mptr->CHINO_LOC[0] != '\0' ) { 816 | sprintf(temp, "CHINO_LOC : %s\n",Mptr->CHINO_LOC); 817 | strcat(outstring, temp); 818 | } 819 | 820 | if ( Mptr->VISNO ) { 821 | sprintf(temp, "VISNO : TRUE\n"); 822 | strcat(outstring, temp); 823 | } 824 | 825 | if ( Mptr->VISNO_LOC[0] != '\0' ) { 826 | sprintf(temp, "VISNO_LOC : %s\n",Mptr->VISNO_LOC); 827 | strcat(outstring, temp); 828 | } 829 | 830 | if ( Mptr->FZRANO ) { 831 | sprintf(temp, "FZRANO : TRUE\n"); 832 | strcat(outstring, temp); 833 | } 834 | 835 | if ( Mptr->TSNO ) { 836 | sprintf(temp, "TSNO : TRUE\n"); 837 | strcat(outstring, temp); 838 | } 839 | 840 | if ( Mptr->DollarSign) { 841 | sprintf(temp, "DOLLAR $IGN INDCATR : TRUE\n"); 842 | strcat(outstring, temp); 843 | } 844 | 845 | if ( Mptr->horiz_vsby[ 0 ] != '\0' ) { 846 | sprintf(temp, "HORIZ VISIBILITY : %s\n",Mptr->horiz_vsby); 847 | strcat(outstring, temp); 848 | } 849 | 850 | if ( Mptr->dir_min_horiz_vsby[ 0 ] != '\0' ) { 851 | sprintf(temp, "DIR MIN HORIZ VSBY : %s\n",Mptr->dir_min_horiz_vsby); 852 | strcat(outstring, temp); 853 | } 854 | 855 | if ( Mptr->CAVOK ) { 856 | sprintf(temp, "CAVOK : TRUE\n"); 857 | strcat(outstring, temp); 858 | } 859 | 860 | 861 | if( Mptr->VertVsby != MAXINT ) { 862 | sprintf(temp, "Vert. Vsby (meters) : %d\n", 863 | Mptr->VertVsby ); 864 | strcat(outstring, temp); 865 | } 866 | 867 | if ( Mptr->QFE != MAXINT ) { 868 | sprintf(temp, "QFE : %d\n", Mptr->QFE); 869 | strcat(outstring, temp); 870 | } 871 | 872 | if ( Mptr->VOLCASH ) { 873 | sprintf(temp, "VOLCANIC ASH : TRUE\n"); 874 | strcat(outstring, temp); 875 | } 876 | 877 | if ( Mptr->min_vrbl_wind_dir != MAXINT ) { 878 | sprintf(temp, "MIN VRBL WIND DIR : %d\n",Mptr->min_vrbl_wind_dir); 879 | strcat(outstring, temp); 880 | } 881 | if ( Mptr->max_vrbl_wind_dir != MAXINT ) { 882 | sprintf(temp, "MAX VRBL WIND DIR : %d\n",Mptr->max_vrbl_wind_dir); 883 | strcat(outstring, temp); 884 | } 885 | 886 | 887 | strcat(outstring, "\n\n\n"); 888 | } 889 | 890 | 891 | void print_decoded_metar (Decoded_METAR *Mptr) 892 | { 893 | char stringbuf[5000]; 894 | 895 | sprint_metar(stringbuf, Mptr); 896 | fputs(stringbuf, stdout); 897 | } 898 | 899 | // vim: set ts=4 sw=4 sts=4 noet : 900 | -------------------------------------------------------------------------------- /src/stspack2.c: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "local.h" /* standard header file */ 21 | 22 | /********************************************************************/ 23 | /* */ 24 | /* Title: stspack2 */ 25 | /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */ 26 | /* Date: 05 Oct 1992 */ 27 | /* Programmer: ALLAN DARLING */ 28 | /* Language: C/2 */ 29 | /* */ 30 | /* Abstract: The stspack2 package contains functions to */ 31 | /* perform the isalnum through isxdigit functions */ 32 | /* on strings. The functions come in four forms: */ 33 | /* those that test NULL delimited strings and are */ 34 | /* named in the form sxxxxxxx, those that test at */ 35 | /* most n characters and are named in the form */ 36 | /* nxxxxxxx, those that search forward in a string */ 37 | /* and are named in the form nxtyyyyy, and those */ 38 | /* that search backward in a string and are named */ 39 | /* in the form lstyyyyy. */ 40 | /* */ 41 | /* The xxxxxxx is the name of the test applied to */ 42 | /* each character in the string, such as isalpha, */ 43 | /* thus a function to test a NULL delimited string */ 44 | /* an return a nonzero value if all characters in */ 45 | /* the string are digits is named sisdigit. */ 46 | /* */ 47 | /* The yyyyy is the name of the test applied to */ 48 | /* characters in a string, minus the 'is' prefix. */ 49 | /* Thus a function to find the next digit in a NULL */ 50 | /* delimited string and return a pointer to it is */ 51 | /* named nxtdigit. */ 52 | /* */ 53 | /* The only exception to the naming rule is for the */ 54 | /* functions that test for hexadecimal digits. */ 55 | /* These are named sisxdigi, nisxdigi, nxtxdigi, */ 56 | /* and lstxdigi because of the eight character */ 57 | /* function name limitation. */ 58 | /* */ 59 | /* The nxxxxxxx class of functions will test up to */ 60 | /* n characters or the first NULL character */ 61 | /* encountered, whichever comes first. For all */ 62 | /* classes of functions, the string sentinal is */ 63 | /* not included in the test. */ 64 | /* */ 65 | /* External Functions Called: */ 66 | /* isalnum, isalpha, iscntrl, isdigit, isgraph, */ 67 | /* islower, isprint, ispunct, isspace, isupper, */ 68 | /* isxdigit. */ 69 | /* */ 70 | /* Input: For sxxxxxxx class functions, a pointer to a */ 71 | /* NULL delimited character string. */ 72 | /* */ 73 | /* For nxtyyyyy class functions, a pointer to a */ 74 | /* NULL delimited character string. */ 75 | /* */ 76 | /* for nxxxxxxx class functions, a pointer to a */ 77 | /* character array, and a positive, nonzero integer.*/ 78 | /* */ 79 | /* for lstyyyyy class functions, a pointer to a */ 80 | /* character array, and a positive, nonzero integer.*/ 81 | /* */ 82 | /* Output: A nonzero value if the test is true for all */ 83 | /* characters in the string, a zero value otherwise.*/ 84 | /* */ 85 | /* Modification History: */ 86 | /* None. */ 87 | /* */ 88 | /********************************************************************/ 89 | 90 | int nisalnum(char *s, int n) { 91 | 92 | for (; *s && n; s++, n--) 93 | 94 | if (!isalnum(*s)) 95 | return (0); 96 | 97 | return (1); 98 | 99 | } /* end nisalnum */ 100 | 101 | 102 | int nisalpha(char *s, int n) { 103 | 104 | for (; *s && n; s++, n--) 105 | 106 | if (!isalpha(*s)) 107 | return (0); 108 | 109 | return (1); 110 | 111 | } /* end nisalpha */ 112 | 113 | 114 | int niscntrl(char *s, int n) { 115 | 116 | for (; *s && n; s++, n--) 117 | 118 | if (!iscntrl(*s)) 119 | return (0); 120 | 121 | return (1); 122 | 123 | } /* end niscntrl */ 124 | 125 | 126 | int nisdigit(char *s, int n) { 127 | 128 | for (; *s && n; s++, n--) 129 | 130 | if (!isdigit(*s)) 131 | return (0); 132 | 133 | return (1); 134 | 135 | } /* end nisdigit */ 136 | 137 | 138 | int nisgraph(char *s, int n) { 139 | 140 | for (; *s && n; s++, n--) 141 | 142 | if (!isgraph(*s)) 143 | return (0); 144 | 145 | return (1); 146 | 147 | } /* end nisgraph */ 148 | 149 | 150 | int nislower(char *s, int n) { 151 | 152 | for (; *s && n; s++, n--) 153 | 154 | if (!islower(*s)) 155 | return (0); 156 | 157 | return (1); 158 | 159 | } /* end nislower */ 160 | 161 | 162 | int nisprint(char *s, int n) { 163 | 164 | for (; *s && n; s++, n--) 165 | 166 | if (!isprint(*s)) 167 | return (0); 168 | 169 | return (1); 170 | 171 | } /* end nisprint */ 172 | 173 | 174 | int nispunct(char *s, int n) { 175 | 176 | for (; *s && n; s++, n--) 177 | 178 | if (!ispunct(*s)) 179 | return (0); 180 | 181 | return (1); 182 | 183 | } /* end nispunct */ 184 | 185 | 186 | int nisspace(char *s, int n) { 187 | 188 | for (; *s && n; s++, n--) 189 | 190 | if (!isspace(*s)) 191 | return (0); 192 | 193 | return (1); 194 | 195 | } /* end nisspace */ 196 | 197 | 198 | int nisupper(char *s, int n) { 199 | 200 | for (; *s && n; s++, n--) 201 | 202 | if (!isupper(*s)) 203 | return (0); 204 | 205 | return (1); 206 | 207 | } /* end nisupper */ 208 | 209 | 210 | int nisxdigi(char *s, int n) { 211 | 212 | for (; *s && n; s++, n--) 213 | 214 | if (!isxdigit(*s)) 215 | return (0); 216 | 217 | return (1); 218 | 219 | } /* end nisxdigi */ 220 | 221 | // vim: set ts=4 sw=4 sts=4 noet : 222 | -------------------------------------------------------------------------------- /src/stspack3.c: -------------------------------------------------------------------------------- 1 | /* 2 | METAR Decoder Software Package Library: Parses Aviation Routine Weather Reports 3 | Copyright (C) 2003 Eric McCarthy 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "local.h" /* standard header file */ 21 | 22 | /********************************************************************/ 23 | /* */ 24 | /* Title: stspack3 */ 25 | /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */ 26 | /* Date: 05 Oct 1992 */ 27 | /* Programmer: ALLAN DARLING */ 28 | /* Language: C/2 */ 29 | /* */ 30 | /* Abstract: The stspack3 package contains functions to */ 31 | /* perform the isalnum through isxdigit functions */ 32 | /* on strings. The functions come in four forms: */ 33 | /* those that test NULL delimited strings and are */ 34 | /* named in the form sxxxxxxx, those that test at */ 35 | /* most n characters and are named in the form */ 36 | /* nxxxxxxx, those that search forward in a string */ 37 | /* and are named in the form nxtyyyyy, and those */ 38 | /* that search backward in a string and are named */ 39 | /* in the form lstyyyyy. */ 40 | /* */ 41 | /* The xxxxxxx is the name of the test applied to */ 42 | /* each character in the string, such as isalpha, */ 43 | /* thus a function to test a NULL delimited string */ 44 | /* an return a nonzero value if all characters in */ 45 | /* the string are digits is named sisdigit. */ 46 | /* */ 47 | /* The yyyyy is the name of the test applied to */ 48 | /* characters in a string, minus the 'is' prefix. */ 49 | /* Thus a function to find the next digit in a NULL */ 50 | /* delimited string and return a pointer to it is */ 51 | /* named nxtdigit. */ 52 | /* */ 53 | /* The only exception to the naming rule is for the */ 54 | /* functions that test for hexadecimal digits. */ 55 | /* These are named sisxdigi, nisxdigi, nxtxdigi, */ 56 | /* and lstxdigi because of the eight character */ 57 | /* function name limitation. */ 58 | /* */ 59 | /* The nxxxxxxx class of functions will test up to */ 60 | /* n characters or the first NULL character */ 61 | /* encountered, whichever comes first. For all */ 62 | /* classes of functions, the string sentinal is */ 63 | /* not included in the test. */ 64 | /* */ 65 | /* External Functions Called: */ 66 | /* isalnum, isalpha, iscntrl, isdigit, isgraph, */ 67 | /* islower, isprint, ispunct, isspace, isupper, */ 68 | /* isxdigit. */ 69 | /* */ 70 | /* Input: For sxxxxxxx class functions, a pointer to a */ 71 | /* NULL delimited character string. */ 72 | /* */ 73 | /* For nxtyyyyy class functions, a pointer to a */ 74 | /* NULL delimited character string. */ 75 | /* */ 76 | /* for nxxxxxxx class functions, a pointer to a */ 77 | /* character array, and a positive, nonzero integer.*/ 78 | /* */ 79 | /* for lstyyyyy class functions, a pointer to a */ 80 | /* character array, and a positive, nonzero integer.*/ 81 | /* */ 82 | /* Output: A nonzero value if the test is true for all */ 83 | /* characters in the string, a zero value otherwise.*/ 84 | /* */ 85 | /* Modification History: */ 86 | /* None. */ 87 | /* */ 88 | /********************************************************************/ 89 | char *nxtalnum(char *s) { 90 | 91 | for (; !isalnum(*s) && *s; s++) ; 92 | 93 | if (*s) 94 | return (s); 95 | else 96 | return (NULL); 97 | 98 | } /* end nxtalnum */ 99 | 100 | 101 | char *nxtalpha(char *s) { 102 | 103 | for (; !isalpha(*s) && *s; s++) ; 104 | 105 | if (*s) 106 | return (s); 107 | else 108 | return (NULL); 109 | 110 | } /* end nxtalpha */ 111 | 112 | 113 | char *nxtcntrl(char *s) { 114 | 115 | for (; !iscntrl(*s) && *s; s++) ; 116 | 117 | if (*s) 118 | return (s); 119 | else 120 | return (NULL); 121 | 122 | } /* end nxtcntrl */ 123 | 124 | 125 | char *nxtdigit(char *s) { 126 | 127 | for (; !isdigit(*s) && *s; s++) ; 128 | 129 | if (*s) 130 | return (s); 131 | else 132 | return (NULL); 133 | 134 | } /* end nxtdigit */ 135 | 136 | 137 | char *nxtgraph(char *s) { 138 | 139 | for (; !isgraph(*s) && *s; s++) ; 140 | 141 | if (*s) 142 | return (s); 143 | else 144 | return (NULL); 145 | 146 | } /* end nxtgraph */ 147 | 148 | 149 | char *nxtlower(char *s) { 150 | 151 | for (; !islower(*s) && *s; s++) ; 152 | 153 | if (*s) 154 | return (s); 155 | else 156 | return (NULL); 157 | 158 | } /* end nxtlower */ 159 | 160 | 161 | char *nxtprint(char *s) { 162 | 163 | for (; !isprint(*s) && *s; s++) ; 164 | 165 | if (*s) 166 | return (s); 167 | else 168 | return (NULL); 169 | 170 | } /* end nxtprint */ 171 | 172 | 173 | char *nxtpunct(char *s) { 174 | 175 | for (; !ispunct(*s) && *s; s++) ; 176 | 177 | if (*s) 178 | return (s); 179 | else 180 | return (NULL); 181 | 182 | } /* end nxtpunct */ 183 | 184 | 185 | char *nxtspace(char *s) { 186 | 187 | for (; !isspace(*s) && *s; s++) ; 188 | 189 | if (*s) 190 | return (s); 191 | else 192 | return (NULL); 193 | 194 | } /* end nxtspace */ 195 | 196 | 197 | char *nxtupper(char *s) { 198 | 199 | for (; !isupper(*s) && *s; s++) ; 200 | 201 | if (*s) 202 | return (s); 203 | else 204 | return (NULL); 205 | 206 | } /* end nxtupper */ 207 | 208 | 209 | char *nxtxdigi(char *s) { 210 | 211 | for (; !isxdigit(*s) && *s; s++) ; 212 | 213 | if (*s) 214 | return (s); 215 | else 216 | return (NULL); 217 | 218 | } /* end nxtxdigi */ 219 | 220 | 221 | // vim: set ts=4 sw=4 sts=4 noet : 222 | --------------------------------------------------------------------------------