Compare commits
209 Commits
RELEASE_0_
...
RELEASE_0_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a2ee54389 | ||
|
|
ab69c03698 | ||
|
|
fab1f4e7a0 | ||
|
|
41eed484c1 | ||
|
|
7d18f9bdde | ||
|
|
3a48c3de7a | ||
|
|
d769a9936b | ||
|
|
1697cb3b1a | ||
|
|
62aa32a417 | ||
|
|
a0d0852838 | ||
|
|
2f479cae69 | ||
|
|
4820d57fa8 | ||
|
|
04e3b0b3c1 | ||
|
|
a7f78b9f68 | ||
|
|
f3d8eb4665 | ||
|
|
090f79b951 | ||
|
|
88c0dbf661 | ||
|
|
9e3822ceaf | ||
|
|
007b0a8fe6 | ||
|
|
7f0ebf8871 | ||
|
|
5414e94a1a | ||
|
|
461dee8657 | ||
|
|
297b6193fe | ||
|
|
4b74e40a5f | ||
|
|
5a9b08dec2 | ||
|
|
5e6f9f79a2 | ||
|
|
e2f93e6ae1 | ||
|
|
93314b59fb | ||
|
|
29269c6686 | ||
|
|
3c84b6e2f6 | ||
|
|
04fb708543 | ||
|
|
df302f277c | ||
|
|
5e63e663bb | ||
|
|
ca10cb2d37 | ||
|
|
c9854153f8 | ||
|
|
129e3c6326 | ||
|
|
66996711ae | ||
|
|
8fe37cea51 | ||
|
|
de64b6f267 | ||
|
|
9a9d9c7cc1 | ||
|
|
a191e9762a | ||
|
|
a7b35c6e22 | ||
|
|
5034346b67 | ||
|
|
661f64b902 | ||
|
|
bbc83f721c | ||
|
|
01f4541331 | ||
|
|
0e4a894f62 | ||
|
|
1c135a9b5b | ||
|
|
e65c85ce73 | ||
|
|
26b58991f9 | ||
|
|
8390df37ca | ||
|
|
371fc73f24 | ||
|
|
921dae5444 | ||
|
|
9b3abbec89 | ||
|
|
6935baba5b | ||
|
|
dec1e32f96 | ||
|
|
710c2ccfcd | ||
|
|
8e66e534ae | ||
|
|
0f5f30b993 | ||
|
|
b199f733f7 | ||
|
|
0cdcf3a3e0 | ||
|
|
8e09486e82 | ||
|
|
0c24b78573 | ||
|
|
1436be9699 | ||
|
|
0489ad7c62 | ||
|
|
c553570533 | ||
|
|
bda112297f | ||
|
|
331a4e4406 | ||
|
|
a9faf8ceff | ||
|
|
2866d1ace9 | ||
|
|
11a74f7a31 | ||
|
|
634a2035ee | ||
|
|
ffada9257d | ||
|
|
e09164e5b3 | ||
|
|
de1a5f3034 | ||
|
|
86e83faef3 | ||
|
|
9f06c8df76 | ||
|
|
6e511de7db | ||
|
|
e34aae9982 | ||
|
|
675b388b8e | ||
|
|
7d239fe4ac | ||
|
|
edd92caba1 | ||
|
|
5c3b4abf42 | ||
|
|
d3a3466b14 | ||
|
|
4399383781 | ||
|
|
bb383998bb | ||
|
|
ffeb174ca1 | ||
|
|
a90d74dde8 | ||
|
|
9d7fd79e76 | ||
|
|
6f29d234eb | ||
|
|
6f5517f602 | ||
|
|
cc43c745b2 | ||
|
|
db8d961b27 | ||
|
|
a0bdec2846 | ||
|
|
5bbcd386fa | ||
|
|
7657632024 | ||
|
|
ab29063a97 | ||
|
|
c06ef23eb1 | ||
|
|
7b2f7aa827 | ||
|
|
7113c10f4b | ||
|
|
14033946e5 | ||
|
|
6e0e056ca7 | ||
|
|
7aa4f0ccdb | ||
|
|
4b04450fa6 | ||
|
|
ad81560be5 | ||
|
|
5c26faa20e | ||
|
|
bd85fa2457 | ||
|
|
430136fdc9 | ||
|
|
a616aa8e55 | ||
|
|
05b9166c25 | ||
|
|
71770eb92e | ||
|
|
2089a2a956 | ||
|
|
488efa2316 | ||
|
|
44551dad2d | ||
|
|
00e0e72bca | ||
|
|
a611b70087 | ||
|
|
757ed2dfe7 | ||
|
|
8971a67aca | ||
|
|
5a343da5cc | ||
|
|
4c77c1691b | ||
|
|
aadff33011 | ||
|
|
25d7705379 | ||
|
|
867ba3c7da | ||
|
|
3f08d9604e | ||
|
|
5d813aa4d0 | ||
|
|
ce3a1ddcb0 | ||
|
|
e37752f957 | ||
|
|
40d920ddc9 | ||
|
|
4362eb79e6 | ||
|
|
f6c9af488b | ||
|
|
a34ac6a596 | ||
|
|
3b3baa996b | ||
|
|
d6b81a9721 | ||
|
|
a460c753e7 | ||
|
|
9f59e956fa | ||
|
|
bd02eb8e6b | ||
|
|
a266790a25 | ||
|
|
3462e3b6c1 | ||
|
|
ed29944b91 | ||
|
|
a0251b3256 | ||
|
|
557474095f | ||
|
|
b7dd267807 | ||
|
|
58a0b1d2c3 | ||
|
|
d8acc3a8f2 | ||
|
|
5f21c75e02 | ||
|
|
79d72b6292 | ||
|
|
aa67c738a1 | ||
|
|
117628bf7e | ||
|
|
70dbbf52f0 | ||
|
|
99bf2c6f9e | ||
|
|
3fdeea7f65 | ||
|
|
ea9d110036 | ||
|
|
16ad232e0d | ||
|
|
5b8e5fce20 | ||
|
|
0633d703d0 | ||
|
|
ec6ce9fcd8 | ||
|
|
c9e53d5a30 | ||
|
|
828e10773c | ||
|
|
34b5c1a1b9 | ||
|
|
b2a7975493 | ||
|
|
f0af686d17 | ||
|
|
eda1121054 | ||
|
|
d97eb240d9 | ||
|
|
8c296d96c7 | ||
|
|
65a49bb6e4 | ||
|
|
cfedc90fdd | ||
|
|
5665a62938 | ||
|
|
36521869ae | ||
|
|
84fd7a49ad | ||
|
|
24b5f05522 | ||
|
|
17415424bf | ||
|
|
920c0fdb62 | ||
|
|
40414f2823 | ||
|
|
3d43bc0480 | ||
|
|
7bee5f1ab6 | ||
|
|
a43f5c8d21 | ||
|
|
8361069344 | ||
|
|
c9661e2732 | ||
|
|
bd13cf84a1 | ||
|
|
e54cfc002b | ||
|
|
5aac63d9f5 | ||
|
|
6a19bbee7d | ||
|
|
2e5c4b4515 | ||
|
|
79d1aaf7f5 | ||
|
|
a659969bcf | ||
|
|
53bdf9dac4 | ||
|
|
ad394fb090 | ||
|
|
92a123a47d | ||
|
|
755173bd2e | ||
|
|
27477402c9 | ||
|
|
dc9c41e119 | ||
|
|
3c7f9e7ba4 | ||
|
|
fbf018598e | ||
|
|
83b4dcb55c | ||
|
|
5812571df4 | ||
|
|
b1c688abe8 | ||
|
|
f4b30bbdd7 | ||
|
|
e4008862ce | ||
|
|
2b7079eed2 | ||
|
|
983685fde3 | ||
|
|
eef1cc716d | ||
|
|
34e2a9dc37 | ||
|
|
1786692406 | ||
|
|
c37afce303 | ||
|
|
1ea99cdd4d | ||
|
|
4c1d22b8a6 | ||
|
|
5f22c93db7 | ||
|
|
13a42f1d9e | ||
|
|
c4d5d85c3e |
10
.cvsignore
10
.cvsignore
@@ -7,3 +7,13 @@ config.cache
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
do-config.sh
|
||||
.cdtproject
|
||||
.project
|
||||
config.guess
|
||||
config.sub
|
||||
depcomp
|
||||
INSTALL
|
||||
install-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
|
||||
2
Doxyfile
2
Doxyfile
@@ -22,7 +22,7 @@ PROJECT_NAME = SimGear
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.3.4
|
||||
PROJECT_NUMBER = 0.3.7
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
EXTRA_DIST = \
|
||||
acinclude.m4 \
|
||||
autogen.sh \
|
||||
DoxygenMain.cxx
|
||||
DoxygenMain.cxx \
|
||||
README.MSVC \
|
||||
README.metakit \
|
||||
README.zlib \
|
||||
SimGear.dsp \
|
||||
SimGear.dsw
|
||||
@@ -11,7 +10,7 @@ EXTRA_DIST = \
|
||||
SUBDIRS = src-libs simgear
|
||||
|
||||
dist-hook:
|
||||
(cd $(top_srcdir); $(HOME)/projects/FlightGear-0.9/admin/am2dsp.pl)
|
||||
(cd $(top_srcdir); $(HOME)/Projects/FlightGear-0.9/admin/am2dsp.pl)
|
||||
|
||||
#
|
||||
# Rule to build RPM distribution package
|
||||
|
||||
43
NEWS
43
NEWS
@@ -1,3 +1,46 @@
|
||||
New in 0.3.7
|
||||
* October 12, 2004
|
||||
|
||||
* Add support for parsing xml from an in memory buffer, not just a file.
|
||||
* Don't reduce visibility for a "clear" cloud layer.
|
||||
* Add support for audio orientation (direction and cone) for internal
|
||||
view and tower view.
|
||||
* Add support for drawing from display lists rather than in immediate mode.
|
||||
This provides a big performance improvement on many systems.
|
||||
|
||||
|
||||
New in 0.3.6
|
||||
* July 29, 2004
|
||||
|
||||
* Better MinGW support
|
||||
* A bit better handling of OpenAL under Cygwin
|
||||
* Switched audio system from plib's "sl/sm" to OpenAL.
|
||||
* Add support for scaling an object based on distance. The scaling
|
||||
factor is determined by a lookup table based on distance.
|
||||
* Add a "flash" animation type.
|
||||
* Fix cloud positioning/animation bugs.
|
||||
* Fix an off-by-one error in props_io.cxx
|
||||
* Clip audio gain (volume) to 1.0
|
||||
|
||||
|
||||
New in 0.3.5
|
||||
* March 26, 2004
|
||||
|
||||
* Added Andy's nasal interpreter for small built in scripting tasks.
|
||||
Nasal integrates nicely with FlightGear's property system.
|
||||
* Added new (much simpler) metar parsing code (removed older more
|
||||
complex code.)
|
||||
* Support VASI/PAPI lights correctly.
|
||||
* Fixes to cloud animation.
|
||||
* Updates to sky dome coloring as well as sun/moon coloring.
|
||||
* Vary environment lighting with visibility (subtlely.)
|
||||
* Support control of alpha test in model animation.
|
||||
* Complete rewrite of the event manager.
|
||||
* Updates to low level socket code to make it more flexible.
|
||||
* Win32 serial port communication fixes.
|
||||
* sg_geodesy rewritten to be more accurate and robust and symmetric.
|
||||
|
||||
|
||||
New in 0.3.4
|
||||
* October 22, 2003
|
||||
|
||||
|
||||
496
SimGear.dsp
496
SimGear.dsp
@@ -570,200 +570,20 @@ SOURCE=.\simgear\math\fastmath.cxx
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Lib_sgmetar"
|
||||
# Begin Group "Lib_sgenvironment"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Antoi.cpp
|
||||
SOURCE=.\simgear\environment\metar.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
# PROP Intermediate_Dir "Release\Lib_sgenvironment"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Charcmp.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Dcdmetar.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Dcdmtrmk.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Drvmetar.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Fracpart.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Local.h
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Metar.h
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\MetarReport.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\MetarStation.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Prtdmetr.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Stspack2.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\metar\Stspack3.cpp
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmetar"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmetar"
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgenvironment"
|
||||
|
||||
!ENDIF
|
||||
|
||||
@@ -861,6 +681,265 @@ SOURCE=.\simgear\misc\zfstream.cxx
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\misc\interpolator.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmisc"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmisc"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Lib_sgnasal"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\code.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\code.h
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\codegen.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\data.h
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\debug.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\gc.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\hash.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\lex.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\lib.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\mathlib.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\misc.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\nasal.h
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\parse.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\parse.h
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\string.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\nasal\vector.c
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgnasal"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Lib_sgprops"
|
||||
@@ -1015,6 +1094,21 @@ SOURCE=.\simgear\scene\model\animation.cxx
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\scene\model\custtrans.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmodel"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmodel"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\scene\model\location.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
@@ -1060,6 +1154,21 @@ SOURCE=.\simgear\scene\model\modellib.cxx
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\scene\model\personality.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgmodel"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgmodel"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\scene\model\placement.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
@@ -2284,7 +2393,7 @@ SOURCE=.\simgear\serial\serial.cxx
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\sound\sound.cxx
|
||||
SOURCE=.\simgear\sound\sample_openal.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
@@ -2299,7 +2408,22 @@ SOURCE=.\simgear\sound\sound.cxx
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\sound\soundmgr.cxx
|
||||
SOURCE=.\simgear\sound\soundmgr_openal.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release\Lib_sgsound"
|
||||
|
||||
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
|
||||
|
||||
# PROP Intermediate_Dir "Debug\Lib_sgsound"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simgear\sound\xmlsound.cxx
|
||||
|
||||
!IF "$(CFG)" == "SimGear - Win32 Release"
|
||||
|
||||
|
||||
71
configure.ac
71
configure.ac
@@ -10,7 +10,7 @@ dnl Require at least automake 2.52
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
dnl Initialize the automake stuff
|
||||
AM_INIT_AUTOMAKE(SimGear, 0.3.4)
|
||||
AM_INIT_AUTOMAKE(SimGear, 0.3.7)
|
||||
|
||||
dnl Specify KAI C++ compiler and flags.
|
||||
dnl Borrowed with slight modification from blitz distribution.
|
||||
@@ -47,8 +47,25 @@ case "${host}" in
|
||||
if test "x$CXX" = "xCC" -o "x$CXX" = "xccache CC"; then
|
||||
AR="$CXX -ar"
|
||||
ARFLAGS="-o"
|
||||
CXXFLAGS="$CXXFLAGS -I$(top_srcdir)/simgear/compatibility"
|
||||
CXXFLAGS="$CXXFLAGS -I$(top_srcdir)/simgear/compatibility/MIPSpro740"
|
||||
compatibility_DIR="compatibility"
|
||||
MIPSpro_DIRS="MIPSpro740"
|
||||
AC_MSG_CHECKING([for MIPSpro compiler version 7.4 or newer])
|
||||
AC_TRY_RUN([
|
||||
int main() {
|
||||
if ( _COMPILER_VERSION < 740 ) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
], AC_MSG_RESULT(yes),
|
||||
[ AC_MSG_RESULT(no)
|
||||
CXXFLAGS="$CXXFLAGS -I$(top_srcdir)/simgear/compatibility/MIPSpro721"
|
||||
MIPSpro_DIRS="$(MIPSpro_DIRS) MIPSpro721"
|
||||
AC_MSG_WARN([Using our own subset of the STL headers])
|
||||
], AC_MSG_RESULT(yes))
|
||||
AC_SUBST(MIPSpro_DIRS)
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
@@ -96,6 +113,13 @@ else
|
||||
fi
|
||||
AM_CONDITIONAL(ENABLE_JPEG_SERVER, test "x$with_jpeg_factory" = "xyes")
|
||||
|
||||
# specify the plib location
|
||||
AC_ARG_WITH(plib, [ --with-plib=PREFIX Specify the prefix path to plib])
|
||||
|
||||
if test "x$with_plib" != "x" ; then
|
||||
echo "plib prefix is $with_plib"
|
||||
EXTRA_DIRS="${EXTRA_DIRS} $with_plib"
|
||||
fi
|
||||
|
||||
dnl Determine an extra directories to add to include/lib search paths
|
||||
case "${host}" in
|
||||
@@ -110,7 +134,7 @@ case "${host}" in
|
||||
if test -d /opt/X11R6 ; then
|
||||
EXTRA_DIR2="/opt/X11R6"
|
||||
fi
|
||||
EXTRA_DIRS="$EXTRA_DIR1 $EXTRA_DIR2"
|
||||
EXTRA_DIRS="${EXTRA_DIRS} $EXTRA_DIR1 $EXTRA_DIR2"
|
||||
;;
|
||||
|
||||
esac
|
||||
@@ -246,7 +270,35 @@ esac
|
||||
opengl_LIBS="$LIBS"
|
||||
LIBS="$base_LIBS"
|
||||
|
||||
dnl check for OpenAL libraries
|
||||
case "${host}" in
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
dnl CygWin under Windoze.
|
||||
|
||||
AC_SEARCH_LIBS(alGenBuffers, openal32)
|
||||
AC_SEARCH_LIBS(alutInit, [ openal32 ALut ] )
|
||||
LIBS="$LIBS -lwinmm -ldsound -ldxguid -lole32"
|
||||
;;
|
||||
|
||||
*-apple-darwin*)
|
||||
dnl Mac OS X
|
||||
|
||||
LIBS="$LIBS -framework IOKit -framework OpenAL"
|
||||
;;
|
||||
|
||||
*)
|
||||
dnl default unix style machines
|
||||
|
||||
AC_SEARCH_LIBS(alGenBuffers, openal)
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
openal_LIBS="$LIBS"
|
||||
LIBS="$base_LIBS"
|
||||
|
||||
AC_SUBST(base_LIBS)
|
||||
AC_SUBST(openal_LIBS)
|
||||
AC_SUBST(opengl_LIBS)
|
||||
AC_SUBST(thread_LIBS)
|
||||
AC_SUBST(network_LIBS)
|
||||
@@ -333,11 +385,14 @@ AC_HEADER_TIME
|
||||
AC_STRUCT_TM
|
||||
|
||||
dnl Checks for library functions.
|
||||
old_LIBS=$LIBS
|
||||
LIBS="$base_LIBS $network_LIBS $opengl_LIBS"
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS( \
|
||||
AC_CHECK_FUNCS( [ \
|
||||
ftime gettimeofday timegm memcpy bcopy mktime strstr rand \
|
||||
random drand48 setitimer getitimer signal GetLocalTime rint getrusage )
|
||||
random drand48 setitimer getitimer signal GetLocalTime rint getrusage ] )
|
||||
LIBS=$old_LIBS
|
||||
|
||||
AM_CONFIG_HEADER(simgear/simgear_config.h)
|
||||
|
||||
@@ -348,17 +403,21 @@ AC_CONFIG_FILES([ \
|
||||
simgear/Makefile \
|
||||
simgear/version.h \
|
||||
simgear/compatibility/Makefile \
|
||||
simgear/compatibility/MIPSpro721/Makefile \
|
||||
simgear/compatibility/MIPSpro740/Makefile \
|
||||
simgear/bucket/Makefile \
|
||||
simgear/debug/Makefile \
|
||||
simgear/ephemeris/Makefile \
|
||||
simgear/io/Makefile \
|
||||
simgear/magvar/Makefile \
|
||||
simgear/math/Makefile \
|
||||
simgear/metar/Makefile \
|
||||
simgear/environment/Makefile \
|
||||
simgear/misc/Makefile \
|
||||
simgear/nasal/Makefile \
|
||||
simgear/props/Makefile \
|
||||
simgear/route/Makefile \
|
||||
simgear/scene/Makefile \
|
||||
simgear/scene/fgsg/Makefile \
|
||||
simgear/scene/material/Makefile \
|
||||
simgear/scene/model/Makefile \
|
||||
simgear/scene/sky/Makefile \
|
||||
|
||||
@@ -5,7 +5,7 @@ SGTHREAD_DIR =
|
||||
endif
|
||||
|
||||
# METAR_DIRS =
|
||||
METAR_DIRS = metar
|
||||
METAR_DIRS = environment
|
||||
|
||||
EXTRA_DIST = simgear_config.h.vc5 version.h.in
|
||||
|
||||
@@ -24,6 +24,7 @@ SUBDIRS = \
|
||||
magvar \
|
||||
math \
|
||||
$(METAR_DIRS) \
|
||||
nasal \
|
||||
props \
|
||||
route \
|
||||
scene \
|
||||
@@ -34,4 +35,4 @@ SUBDIRS = \
|
||||
timing \
|
||||
xgl
|
||||
|
||||
DIST_SUBDIRS = $(SUBDIRS) compatibility metar threads
|
||||
DIST_SUBDIRS = $(SUBDIRS) compatibility threads
|
||||
|
||||
@@ -257,14 +257,16 @@ public:
|
||||
// Informational methods.
|
||||
|
||||
/**
|
||||
* @return the lon of the lower left corner of this tile.
|
||||
* @return the lon of the lower left corner of
|
||||
* the 1x1 chunk containing this tile.
|
||||
*/
|
||||
inline int get_lon() const { return lon; }
|
||||
inline int get_chunk_lon() const { return lon; }
|
||||
|
||||
/**
|
||||
* @return the lat of the lower left corner of this tile.
|
||||
* @return the lat of the lower left corner of
|
||||
* the 1x1 chunk containing this tile.
|
||||
*/
|
||||
inline int get_lat() const { return lat; }
|
||||
inline int get_chunk_lat() const { return lat; }
|
||||
|
||||
/**
|
||||
* @return the x coord within the 1x1 degree chunk this tile.
|
||||
|
||||
2
simgear/compatibility/MIPSpro721/.cvsignore
Normal file
2
simgear/compatibility/MIPSpro721/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
14
simgear/compatibility/MIPSpro721/Makefile.am
Normal file
14
simgear/compatibility/MIPSpro721/Makefile.am
Normal file
@@ -0,0 +1,14 @@
|
||||
includedir = @includedir@/compatibility/
|
||||
|
||||
include_HEADERS = \
|
||||
iostream \
|
||||
strstream \
|
||||
sstream \
|
||||
istream \
|
||||
fstream \
|
||||
iterator \
|
||||
iomanip \
|
||||
new \
|
||||
streambuf \
|
||||
\
|
||||
irix_string
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
namespace std {
|
||||
using ::fstream;
|
||||
using ::ifstream;
|
||||
using ::ofstream;
|
||||
using ::ifstream;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
# include <iomanip.h>
|
||||
|
||||
namespace std {
|
||||
|
||||
using ::setw;
|
||||
using ::setprecision;
|
||||
|
||||
inline int setfill(int f) { ::setfill(f); }
|
||||
};
|
||||
@@ -2,10 +2,9 @@
|
||||
#ifndef __SG_IOSTREAM
|
||||
#define __SG_IOSTREAM 1
|
||||
|
||||
# include <fstream>
|
||||
|
||||
# if defined(sgi) && !defined(__GNUC__)
|
||||
|
||||
# include <fstream>
|
||||
# include <iostream.h>
|
||||
|
||||
class ios_base : public ios {
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
#ifndef __SGI_HXX
|
||||
#define __SGI_HXX
|
||||
#define __SGI_HXX 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -40,4 +42,6 @@ operator+(const char* lhs, const std::string& rhs)
|
||||
return std::string(lhs) + rhs;
|
||||
}
|
||||
|
||||
#endif // !__SGI_HXX
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !__SGI_HXX */
|
||||
@@ -14,8 +14,7 @@ namespace std {
|
||||
};
|
||||
|
||||
|
||||
class istringstream : public istrstream {
|
||||
};
|
||||
typedef istrstream istringstream;
|
||||
|
||||
};
|
||||
|
||||
2
simgear/compatibility/MIPSpro740/.cvsignore
Normal file
2
simgear/compatibility/MIPSpro740/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
22
simgear/compatibility/MIPSpro740/Makefile.am
Normal file
22
simgear/compatibility/MIPSpro740/Makefile.am
Normal file
@@ -0,0 +1,22 @@
|
||||
includedir = @includedir@/compatibility
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
||||
include_HEADERS = \
|
||||
cfloat \
|
||||
csetjmp \
|
||||
cstdio \
|
||||
cwchar \
|
||||
cassert \
|
||||
climits \
|
||||
csignal \
|
||||
cstdlib \
|
||||
cwctype \
|
||||
cctype \
|
||||
clocale \
|
||||
cstdarg \
|
||||
cstring \
|
||||
cerrno \
|
||||
cmath \
|
||||
cstddef \
|
||||
ctime
|
||||
@@ -1,33 +1,3 @@
|
||||
includedir = @includedir@/compatibility
|
||||
SUBDIRS = $(MIPSpro_DIRS)
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
||||
include_HEADERS = \
|
||||
cfloat \
|
||||
csetjmp \
|
||||
cstdio \
|
||||
cwchar \
|
||||
iostream \
|
||||
strstream \
|
||||
sstream \
|
||||
cassert \
|
||||
climits \
|
||||
csignal \
|
||||
cstdlib \
|
||||
cwctype \
|
||||
istream \
|
||||
cctype \
|
||||
clocale \
|
||||
cstdarg \
|
||||
cstring \
|
||||
fstream \
|
||||
iterator \
|
||||
cerrno \
|
||||
cmath \
|
||||
cstddef \
|
||||
ctime \
|
||||
iomanip \
|
||||
new \
|
||||
streambuf \
|
||||
\
|
||||
IRIX
|
||||
DIST_SUBDIRS = MIPSpro721 MIPSpro740
|
||||
|
||||
@@ -149,12 +149,6 @@
|
||||
|
||||
#endif // __GNUC__
|
||||
|
||||
#if defined( __MINGW32__ )
|
||||
# define bcopy(from, to, n) memcpy(to, from, n)
|
||||
# define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
/* KAI C++ */
|
||||
#if defined(__KCC)
|
||||
|
||||
@@ -219,7 +213,7 @@
|
||||
# define bcopy(from, to, n) memcpy(to, from, n)
|
||||
# define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
|
||||
|
||||
# if _MSC_VER == 1200 // msvc++ 6.0
|
||||
# if _MSC_VER >= 1200 // msvc++ 6.0 or greater
|
||||
# define SG_NAMESPACES
|
||||
# define SG_HAVE_STD
|
||||
# define SG_HAVE_STD_INCLUDES
|
||||
@@ -235,6 +229,7 @@
|
||||
# define STL_STRING <string>
|
||||
# define STL_STRSTREAM <strstream>
|
||||
|
||||
# define isnan _isnan
|
||||
# define snprintf _snprintf
|
||||
|
||||
# pragma warning(disable: 4786) // identifier was truncated to '255' characters
|
||||
@@ -290,8 +285,6 @@
|
||||
#if defined ( sgi ) && !defined( __GNUC__ )
|
||||
# define SG_HAVE_NATIVE_SGI_COMPILERS
|
||||
|
||||
#include <simgear/compatibility/IRIX>
|
||||
|
||||
# define SG_EXPLICIT_FUNCTION_TMPL_ARGS
|
||||
# define SG_CLASS_PARTIAL_SPECIALIZATION
|
||||
# define SG_NEED_AUTO_PTR
|
||||
@@ -309,7 +302,11 @@
|
||||
# define STL_ITERATOR <iterator>
|
||||
# define STL_FSTREAM <fstream>
|
||||
# define STL_STDEXCEPT <stdexcept>
|
||||
#if (_COMPILER_VERSION < 740)
|
||||
# define STL_STRING <irix_string>
|
||||
#else
|
||||
# define STL_STRING <string>
|
||||
#endif
|
||||
# define STL_STRSTREAM <strstream>
|
||||
|
||||
#pragma set woff 1001,1012,1014,1116,1155,1172,1174
|
||||
@@ -317,6 +314,9 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
#pragma set woff 1682,3303
|
||||
#if (_COMPILER_VERSION >= 740)
|
||||
# pragma set woff 3624
|
||||
#endif
|
||||
#endif
|
||||
|
||||
# define SG_COMPILER_STR "SGI MipsPro compiler version " SG_STRINGIZE(_COMPILER_VERSION)
|
||||
|
||||
@@ -106,21 +106,51 @@
|
||||
#define SG_METER_TO_FEET 3.28083989501312335958
|
||||
|
||||
/** Meters to Nautical Miles. 1 nm = 6076.11549 feet */
|
||||
#define SG_METER_TO_NM 0.00053995680
|
||||
#define SG_METER_TO_NM 0.0005399568034557235
|
||||
|
||||
/** Nautical Miles to Meters */
|
||||
#define SG_NM_TO_METER 1852.0000
|
||||
|
||||
/** Meters to Statute Miles. */
|
||||
#define SG_METER_TO_SM 0.0006213699494949496
|
||||
|
||||
/** Statute Miles to Meters. */
|
||||
#define SG_SM_TO_METER 1609.3412196
|
||||
|
||||
/** Radians to Nautical Miles. 1 nm = 1/60 of a degree */
|
||||
#define SG_NM_TO_RAD 0.00029088820866572159
|
||||
|
||||
/** Nautical Miles to Radians */
|
||||
#define SG_RAD_TO_NM 3437.7467707849392526
|
||||
|
||||
/** Miles per second to Knots */
|
||||
#define SG_MPS_TO_KT 1.9438444924406046432
|
||||
|
||||
/** Knots to Miles per second */
|
||||
#define SG_KT_TO_MPS 0.5144444444444444444
|
||||
|
||||
/** Miles per second to Miles per hour */
|
||||
#define SG_MPS_TO_MPH 2.2369362920544020312
|
||||
|
||||
/** Miles per hour to Miles per second */
|
||||
#define SG_MPH_TO_MPS 0.44704
|
||||
|
||||
/** Meters per second to Kilometers per hour */
|
||||
#define SG_MPS_TO_KMH 3.6
|
||||
|
||||
/** Kilometers per hour to Miles per second */
|
||||
#define SG_KMH_TO_MPS 0.2777777777777777778
|
||||
|
||||
/** Pascal to Inch Mercury */
|
||||
#define SG_PA_TO_INHG 0.0002952998330101010
|
||||
|
||||
/** Inch Mercury to Pascal */
|
||||
#define SG_INHG_TO_PA 3386.388640341
|
||||
|
||||
|
||||
/** For divide by zero avoidance, this will be close enough to zero */
|
||||
#define SG_EPSILON 0.0000001
|
||||
|
||||
|
||||
/** Highest binobj format version we know how to read/write. This starts at
|
||||
* 0 and can go up to 65535 */
|
||||
#define SG_BINOBJ_VERSION 6
|
||||
|
||||
@@ -24,7 +24,8 @@ typedef enum {
|
||||
SG_CLIPPER = 0x00002000,
|
||||
SG_NETWORK = 0x00004000,
|
||||
SG_ATC = 0x00008000,
|
||||
SG_UNDEFD = 0x00010000, // For range checking
|
||||
SG_NASAL = 0x00010000,
|
||||
SG_UNDEFD = 0x00020000, // For range checking
|
||||
|
||||
SG_ALL = 0xFFFFFFFF
|
||||
} sgDebugClass;
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef SG_HAVE_STD_INCLUDES
|
||||
# include <streambuf>
|
||||
# include <iostream>
|
||||
@@ -180,7 +184,23 @@ logbuf::set_log_state( sgDebugClass c, sgDebugPriority p )
|
||||
inline logbuf::int_type
|
||||
logbuf::overflow( int c )
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
static has_console = false;
|
||||
if ( logging_enabled ) {
|
||||
if ( !has_console ) {
|
||||
AllocConsole();
|
||||
freopen("conin$", "r", stdin);
|
||||
freopen("conout$", "w", stdout);
|
||||
freopen("conout$", "w", stderr);
|
||||
has_console = true;
|
||||
}
|
||||
sbuf->sputc(c);
|
||||
}
|
||||
else
|
||||
return EOF == 0 ? 1: 0;
|
||||
#else
|
||||
return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
4
simgear/environment/.cvsignore
Normal file
4
simgear/environment/.cvsignore
Normal file
@@ -0,0 +1,4 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
metar
|
||||
9
simgear/environment/Makefile.am
Normal file
9
simgear/environment/Makefile.am
Normal file
@@ -0,0 +1,9 @@
|
||||
includedir = @includedir@/environment
|
||||
|
||||
lib_LIBRARIES = libsgenvironment.a
|
||||
|
||||
include_HEADERS = metar.hxx
|
||||
|
||||
libsgenvironment_a_SOURCES = metar.cxx
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
1140
simgear/environment/metar.cxx
Normal file
1140
simgear/environment/metar.cxx
Normal file
File diff suppressed because it is too large
Load Diff
261
simgear/environment/metar.hxx
Normal file
261
simgear/environment/metar.hxx
Normal file
@@ -0,0 +1,261 @@
|
||||
// metar interface class
|
||||
//
|
||||
// Written by Melchior FRANZ, started December 2003.
|
||||
//
|
||||
// Copyright (C) 2003 Melchior FRANZ - mfranz@aon.at
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifndef _METAR_HXX
|
||||
#define _METAR_HXX
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
|
||||
SG_USING_STD(vector);
|
||||
SG_USING_STD(map);
|
||||
SG_USING_STD(string);
|
||||
|
||||
const double SGMetarNaN = -1E20;
|
||||
#define NaN SGMetarNaN
|
||||
|
||||
struct Token {
|
||||
char *id;
|
||||
char *text;
|
||||
};
|
||||
|
||||
|
||||
class SGMetar;
|
||||
|
||||
class SGMetarVisibility {
|
||||
friend class SGMetar;
|
||||
public:
|
||||
SGMetarVisibility() :
|
||||
_distance(NaN),
|
||||
_direction(-1),
|
||||
_modifier(EQUALS),
|
||||
_tendency(NONE) {}
|
||||
|
||||
enum Modifier {
|
||||
NOGO,
|
||||
EQUALS,
|
||||
LESS_THAN,
|
||||
GREATER_THAN
|
||||
};
|
||||
|
||||
enum Tendency {
|
||||
NONE,
|
||||
STABLE,
|
||||
INCREASING,
|
||||
DECREASING
|
||||
};
|
||||
|
||||
inline double getVisibility_m() const { return _distance; }
|
||||
inline double getVisibility_ft() const { return _distance == NaN ? NaN : _distance * SG_METER_TO_FEET; }
|
||||
inline double getVisibility_sm() const { return _distance == NaN ? NaN : _distance * SG_METER_TO_SM; }
|
||||
inline int getDirection() const { return _direction; }
|
||||
inline int getModifier() const { return _modifier; }
|
||||
inline int getTendency() const { return _tendency; }
|
||||
|
||||
protected:
|
||||
double _distance;
|
||||
int _direction;
|
||||
int _modifier;
|
||||
int _tendency;
|
||||
};
|
||||
|
||||
|
||||
// runway condition (surface and visibility)
|
||||
class SGMetarRunway {
|
||||
friend class SGMetar;
|
||||
public:
|
||||
SGMetarRunway() :
|
||||
_deposit(0),
|
||||
_extent(-1),
|
||||
_extent_string(0),
|
||||
_depth(NaN),
|
||||
_friction(NaN),
|
||||
_friction_string(0),
|
||||
_comment(0),
|
||||
_wind_shear(false) {}
|
||||
|
||||
inline const char *getDeposit() const { return _deposit; }
|
||||
inline double getExtent() const { return _extent; }
|
||||
inline const char *getExtentString() const { return _extent_string; }
|
||||
inline double getDepth() const { return _depth; }
|
||||
inline double getFriction() const { return _friction; }
|
||||
inline const char *getFrictionString() const { return _friction_string; }
|
||||
inline const char *getComment() const { return _comment; }
|
||||
inline const bool getWindShear() const { return _wind_shear; }
|
||||
inline SGMetarVisibility getMinVisibility() const { return _min_visibility; }
|
||||
inline SGMetarVisibility getMaxVisibility() const { return _max_visibility; }
|
||||
|
||||
protected:
|
||||
SGMetarVisibility _min_visibility;
|
||||
SGMetarVisibility _max_visibility;
|
||||
const char *_deposit;
|
||||
int _extent;
|
||||
const char *_extent_string;
|
||||
double _depth;
|
||||
double _friction;
|
||||
const char *_friction_string;
|
||||
const char *_comment;
|
||||
bool _wind_shear;
|
||||
};
|
||||
|
||||
|
||||
// cloud layer
|
||||
class SGMetarCloud {
|
||||
friend class SGMetar;
|
||||
public:
|
||||
SGMetarCloud() :
|
||||
_coverage(-1),
|
||||
_altitude(NaN),
|
||||
_type(0),
|
||||
_type_long(0) {}
|
||||
|
||||
inline int getCoverage() const { return _coverage; }
|
||||
inline double getAltitude_m() const { return _altitude; }
|
||||
inline double getAltitude_ft() const { return _altitude == NaN ? NaN : _altitude * SG_METER_TO_FEET; }
|
||||
inline char *getTypeString() const { return _type; }
|
||||
inline char *getTypeLongString() const { return _type_long; }
|
||||
|
||||
protected:
|
||||
int _coverage; // quarters: 0 -> clear ... 4 -> overcast
|
||||
double _altitude; // 1000 m
|
||||
char *_type; // CU
|
||||
char *_type_long; // cumulus
|
||||
};
|
||||
|
||||
|
||||
class SGMetar {
|
||||
public:
|
||||
SGMetar(const string& m, const string& proxy = "", const string& port = "", const string &auth = "");
|
||||
~SGMetar();
|
||||
|
||||
enum ReportType {
|
||||
NONE,
|
||||
AUTO,
|
||||
COR,
|
||||
RTD
|
||||
};
|
||||
|
||||
inline const char *getData() const { return _data; }
|
||||
inline const char *getUnusedData() const { return _m; }
|
||||
inline const char *getId() const { return _icao; }
|
||||
inline int getYear() const { return _year; }
|
||||
inline int getMonth() const { return _month; }
|
||||
inline int getDay() const { return _day; }
|
||||
inline int getHour() const { return _hour; }
|
||||
inline int getMinute() const { return _minute; }
|
||||
inline int getReportType() const { return _report_type; }
|
||||
|
||||
inline int getWindDir() const { return _wind_dir; }
|
||||
inline double getWindSpeed_mps() const { return _wind_speed; }
|
||||
inline double getWindSpeed_kmh() const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_KMH; }
|
||||
inline double getWindSpeed_kt() const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_KT; }
|
||||
inline double getWindSpeed_mph() const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_MPH; }
|
||||
|
||||
inline double getGustSpeed_mps() const { return _gust_speed; }
|
||||
inline double getGustSpeed_kmh() const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_KMH; }
|
||||
inline double getGustSpeed_kt() const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_KT; }
|
||||
inline double getGustSpeed_mph() const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_MPH; }
|
||||
|
||||
inline int getWindRangeFrom() const { return _wind_range_from; }
|
||||
inline int getWindRangeTo() const { return _wind_range_to; }
|
||||
|
||||
inline SGMetarVisibility& getMinVisibility() { return _min_visibility; }
|
||||
inline SGMetarVisibility& getMaxVisibility() { return _max_visibility; }
|
||||
inline SGMetarVisibility& getVertVisibility() { return _vert_visibility; }
|
||||
inline SGMetarVisibility *getDirVisibility() { return _dir_visibility; }
|
||||
|
||||
inline double getTemperature_C() const { return _temp; }
|
||||
inline double getTemperature_F() const { return _temp == NaN ? NaN : 1.8 * _temp + 32; }
|
||||
inline double getDewpoint_C() const { return _dewp; }
|
||||
inline double getDewpoint_F() const { return _dewp == NaN ? NaN : 1.8 * _dewp + 32; }
|
||||
inline double getPressure_hPa() const { return _pressure == NaN ? NaN : _pressure / 100; }
|
||||
inline double getPressure_inHg() const { return _pressure == NaN ? NaN : _pressure * SG_PA_TO_INHG; }
|
||||
|
||||
double getRelHumidity() const;
|
||||
|
||||
inline vector<SGMetarCloud>& getClouds() { return _clouds; }
|
||||
inline map<string, SGMetarRunway>& getRunways() { return _runways; }
|
||||
inline vector<string>& getWeather() { return _weather; }
|
||||
|
||||
protected:
|
||||
string _url;
|
||||
int _grpcount;
|
||||
char *_data;
|
||||
char *_m;
|
||||
char _icao[5];
|
||||
int _year;
|
||||
int _month;
|
||||
int _day;
|
||||
int _hour;
|
||||
int _minute;
|
||||
int _report_type;
|
||||
int _wind_dir;
|
||||
double _wind_speed;
|
||||
double _gust_speed;
|
||||
int _wind_range_from;
|
||||
int _wind_range_to;
|
||||
double _temp;
|
||||
double _dewp;
|
||||
double _pressure;
|
||||
|
||||
SGMetarVisibility _min_visibility;
|
||||
SGMetarVisibility _max_visibility;
|
||||
SGMetarVisibility _vert_visibility;
|
||||
SGMetarVisibility _dir_visibility[8];
|
||||
vector<SGMetarCloud> _clouds;
|
||||
map<string, SGMetarRunway> _runways;
|
||||
vector<string> _weather;
|
||||
|
||||
bool scanPreambleDate();
|
||||
bool scanPreambleTime();
|
||||
|
||||
bool scanType();
|
||||
bool scanId();
|
||||
bool scanDate();
|
||||
bool scanModifier();
|
||||
bool scanWind();
|
||||
bool scanVariability();
|
||||
bool scanVisibility();
|
||||
bool scanRwyVisRange();
|
||||
bool scanSkyCondition();
|
||||
bool scanWeather();
|
||||
bool scanTemperature();
|
||||
bool scanPressure();
|
||||
bool scanRunwayReport();
|
||||
bool scanWindShear();
|
||||
bool scanTrendForecast();
|
||||
bool scanColorState();
|
||||
bool scanRemark();
|
||||
bool scanRemainder();
|
||||
|
||||
int scanNumber(char **str, int *num, int min, int max = 0);
|
||||
bool scanBoundary(char **str);
|
||||
const struct Token *scanToken(char **str, const struct Token *list);
|
||||
char *loadData(const char *id, const string& proxy, const string& port, const string &auth);
|
||||
void normalizeData();
|
||||
};
|
||||
|
||||
#undef NaN
|
||||
#endif // _METAR_HXX
|
||||
@@ -49,9 +49,9 @@ tcp_client_LDADD = \
|
||||
socktest_SOURCES = socktest.cxx
|
||||
|
||||
socktest_LDADD = \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/io/libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
-lplibnet -lplibul -lz \
|
||||
$(network_LIBS) \
|
||||
@@ -60,13 +60,17 @@ socktest_LDADD = \
|
||||
lowtest_SOURCES = lowtest.cxx
|
||||
|
||||
lowtest_LDADD = \
|
||||
$(top_builddir)/simgear/io/libsgio.a
|
||||
$(top_builddir)/simgear/io/libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
$(base_LIBS) -lz
|
||||
|
||||
decode_binobj_SOURCES = decode_binobj.cxx
|
||||
|
||||
decode_binobj_LDADD = \
|
||||
$(top_builddir)/simgear/io/libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(base_LIBS) -lz
|
||||
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
|
||||
// calculate the center of a list of points, by taking the halfway
|
||||
// point between the min and max points.
|
||||
static Point3D calc_center( point_list& wgs84_nodes ) {
|
||||
Point3D sgCalcCenter( point_list& wgs84_nodes ) {
|
||||
Point3D p, min, max;
|
||||
|
||||
if ( wgs84_nodes.size() ) {
|
||||
@@ -1145,7 +1145,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
|
||||
for ( i = start; i < end; ++i ) {
|
||||
for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
|
||||
group_nodes.push_back( wgs84_nodes[ tris_v[i][j] ] );
|
||||
bs_center = calc_center( group_nodes );
|
||||
bs_center = sgCalcCenter( group_nodes );
|
||||
bs_radius = sgCalcBoundingRadius( bs_center, group_nodes );
|
||||
}
|
||||
}
|
||||
@@ -1196,7 +1196,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
|
||||
for ( i = start; i < end; ++i ) {
|
||||
for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
|
||||
group_nodes.push_back( wgs84_nodes[ strips_v[i][j] ] );
|
||||
bs_center = calc_center( group_nodes );
|
||||
bs_center = sgCalcCenter( group_nodes );
|
||||
bs_radius = sgCalcBoundingRadius( bs_center, group_nodes );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +221,16 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \relates SGBinObject
|
||||
* Calculate the center of a list of points, by taking the halfway
|
||||
* point between the min and max points.
|
||||
* @param wgs84_nodes list of points in wgs84 coordinates
|
||||
* @return center point
|
||||
*/
|
||||
Point3D sgCalcCenter( point_list& wgs84_nodes );
|
||||
|
||||
|
||||
/**
|
||||
* \relates SGBinObject
|
||||
* Calculate the bounding sphere of a set of nodes.
|
||||
|
||||
@@ -133,7 +133,7 @@ int SGSerial::write( const char *buf, const int length ) {
|
||||
int result = port.write_port( buf, length );
|
||||
|
||||
if ( result != length ) {
|
||||
SG_LOG( SG_IO, SG_ALERT, "Error writing data: " << device );
|
||||
SG_LOG( SG_IO, SG_WARN, "Error writing data: " << device );
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include STL_IOSTREAM
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "sg_socket.hxx"
|
||||
@@ -42,7 +44,8 @@ SGSocket::SGSocket( const string& host, const string& port_,
|
||||
client(0),
|
||||
is_tcp(false),
|
||||
is_server(false),
|
||||
first_read(false)
|
||||
first_read(false),
|
||||
timeout(0)
|
||||
{
|
||||
if (!init)
|
||||
{
|
||||
@@ -218,7 +221,14 @@ SGSocket::read( char *buf, int length )
|
||||
|
||||
if (result > 0)
|
||||
{
|
||||
result = sock.recv( buf, length );
|
||||
if (is_tcp && is_server)
|
||||
{
|
||||
result = client->recv( buf, length );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = sock.recv( buf, length );
|
||||
}
|
||||
|
||||
if ( result != length )
|
||||
{
|
||||
@@ -250,7 +260,7 @@ SGSocket::readline( char *buf, int length )
|
||||
// read a chunk, keep in the save buffer until we have the
|
||||
// requested amount read
|
||||
|
||||
if (is_tcp)
|
||||
if (is_tcp && is_server)
|
||||
{
|
||||
char *buf_ptr = save_buf + save_len;
|
||||
result = client->recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
|
||||
@@ -323,7 +333,7 @@ SGSocket::write( const char *buf, const int length )
|
||||
|
||||
if ( s->send( buf, length ) < 0 )
|
||||
{
|
||||
SG_LOG( SG_IO, SG_ALERT, "Error writing to socket: " << port );
|
||||
SG_LOG( SG_IO, SG_WARN, "Error writing to socket: " << port );
|
||||
error_condition = true;
|
||||
}
|
||||
|
||||
@@ -379,7 +389,7 @@ SGSocket::poll()
|
||||
netSocket* writers[1];
|
||||
writers[0] = 0;
|
||||
|
||||
int result = netSocket::select( readers, writers, 0 );
|
||||
int result = netSocket::select( readers, writers, timeout );
|
||||
|
||||
if (result > 0 && is_server && client == 0)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,7 @@ private:
|
||||
bool is_tcp;
|
||||
bool is_server;
|
||||
bool first_read;
|
||||
int timeout;
|
||||
|
||||
static bool init;
|
||||
|
||||
@@ -156,6 +157,9 @@ public:
|
||||
*/
|
||||
bool nonblock();
|
||||
|
||||
// set timeout (default: 0)
|
||||
inline void set_timeout(int i) { timeout = i; }
|
||||
|
||||
/** @return the remote host name */
|
||||
inline string get_hostname() const { return hostname; }
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ int SGSocketUDP::write( const char *buf, const int length ) {
|
||||
bool error_condition = false;
|
||||
|
||||
if ( sock.send( buf, length, 0 ) < 0 ) {
|
||||
SG_LOG( SG_IO, SG_ALERT, "Error writing to socket: " << port );
|
||||
SG_LOG( SG_IO, SG_WARN, "Error writing to socket: " << port );
|
||||
error_condition = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,9 +9,17 @@
|
||||
* IDSIA, Lugano, Switzerland
|
||||
* http://www.inf.ethz.ch/~schraudo/pubs/exp.pdf
|
||||
*
|
||||
* Base-2 exp, Laurent de Soras
|
||||
* http://www.musicdsp.org/archive.php?classid=5#106
|
||||
*
|
||||
* Fast log() Function, by Laurent de Soras:
|
||||
* http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-Fastlogfunction&forum=totd&id=-1
|
||||
*
|
||||
* Sin, Cos, Tan approximation
|
||||
* http://www.musicdsp.org/showArchiveComment.php?ArchiveID=115
|
||||
*
|
||||
* fast floating point power computation:
|
||||
* http://playstation2-linux.com/download/adam/power.c
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -21,6 +29,7 @@
|
||||
|
||||
|
||||
#include "fastmath.hxx"
|
||||
#define SGD_PI_2 1.57079632679489661923
|
||||
|
||||
/**
|
||||
* This function is on avarage 9 times faster than the system exp() function
|
||||
@@ -41,11 +50,76 @@ double fast_exp(double val) {
|
||||
const double a = 1048576/M_LN2;
|
||||
const double b_c = 1072632447; /* 1072693248 - 60801 */
|
||||
|
||||
_eco.n.i = a*val + b_c;
|
||||
_eco.n.i = (int)(a*val + b_c);
|
||||
|
||||
return _eco.d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Linear approx. between 2 integer values of val. Uses 32-bit integers.
|
||||
* Not very efficient but faster than exp()
|
||||
*/
|
||||
double fast_exp2( const double val )
|
||||
{
|
||||
int e;
|
||||
double ret;
|
||||
|
||||
if (val >= 0) {
|
||||
e = int (val);
|
||||
ret = val - (e - 1);
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
((*((int *) &ret)) &= ~(2047 << 20)) += (e + 1023) << 20;
|
||||
#else
|
||||
((*(1 + (int *) &ret)) &= ~(2047 << 20)) += (e + 1023) << 20;
|
||||
#endif
|
||||
} else {
|
||||
e = int (val + 1023);
|
||||
ret = val - (e - 1024);
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
((*((int *) &ret)) &= ~(2047 << 20)) += e << 20;
|
||||
#else
|
||||
((*(1 + (int *) &ret)) &= ~(2047 << 20)) += e << 20;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
float _fast_log2(const float val)
|
||||
{
|
||||
float result, tmp;
|
||||
float mp = 0.346607f;
|
||||
|
||||
result = *(int*)&val;
|
||||
result *= 1.0/(1<<23);
|
||||
result = result - 127;
|
||||
|
||||
tmp = result - floor(result);
|
||||
tmp = (tmp - tmp*tmp) * mp;
|
||||
return tmp + result;
|
||||
}
|
||||
|
||||
float _fast_pow2(const float val)
|
||||
{
|
||||
float result;
|
||||
|
||||
float mp = 0.33971f;
|
||||
float tmp = val - floor(val);
|
||||
tmp = (tmp - tmp*tmp) * mp;
|
||||
|
||||
result = val + 127 - tmp;
|
||||
result *= (1<<23);
|
||||
*(int*)&result = (int)result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* While we're on the subject, someone might have use for these as well?
|
||||
@@ -63,3 +137,155 @@ void fast_BSR(float &x, register unsigned long shiftAmount) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fastpow(f,n) gives a rather *rough* estimate of a float number f to the
|
||||
* power of an integer number n (y=f^n). It is fast but result can be quite a
|
||||
* bit off, since we directly mess with the floating point exponent.
|
||||
*
|
||||
* Use it only for getting rough estimates of the values and where precision
|
||||
* is not that important.
|
||||
*/
|
||||
float fast_pow(const float f, const int n)
|
||||
{
|
||||
long *lp,l;
|
||||
lp=(long*)(&f);
|
||||
l=*lp;l-=0x3F800000l;l<<=(n-1);l+=0x3F800000l;
|
||||
*lp=l;
|
||||
return f;
|
||||
}
|
||||
|
||||
float fast_root(const float f, const int n)
|
||||
{
|
||||
long *lp,l;
|
||||
lp=(long*)(&f);
|
||||
l=*lp;l-=0x3F800000l;l>>=(n-1);l+=0x3F800000l;
|
||||
*lp=l;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Code for approximation of cos, sin, tan and inv sin, etc.
|
||||
* Surprisingly accurate and very usable.
|
||||
*
|
||||
* Domain:
|
||||
* Sin/Cos [0, pi/2]
|
||||
* Tan [0,pi/4]
|
||||
* InvSin/Cos [0, 1]
|
||||
* InvTan [-1, 1]
|
||||
*/
|
||||
|
||||
float fast_sin(const float val)
|
||||
{
|
||||
float fASqr = val*val;
|
||||
float fResult = -2.39e-08f;
|
||||
fResult *= fASqr;
|
||||
fResult += 2.7526e-06f;
|
||||
fResult *= fASqr;
|
||||
fResult -= 1.98409e-04f;
|
||||
fResult *= fASqr;
|
||||
fResult += 8.3333315e-03f;
|
||||
fResult *= fASqr;
|
||||
fResult -= 1.666666664e-01f;
|
||||
fResult *= fASqr;
|
||||
fResult += 1.0f;
|
||||
fResult *= val;
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
float fast_cos(const float val)
|
||||
{
|
||||
float fASqr = val*val;
|
||||
float fResult = -2.605e-07f;
|
||||
fResult *= fASqr;
|
||||
fResult += 2.47609e-05f;
|
||||
fResult *= fASqr;
|
||||
fResult -= 1.3888397e-03f;
|
||||
fResult *= fASqr;
|
||||
fResult += 4.16666418e-02f;
|
||||
fResult *= fASqr;
|
||||
fResult -= 4.999999963e-01f;
|
||||
fResult *= fASqr;
|
||||
fResult += 1.0f;
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
float fast_tan(const float val)
|
||||
{
|
||||
float fASqr = val*val;
|
||||
float fResult = 9.5168091e-03f;
|
||||
fResult *= fASqr;
|
||||
fResult += 2.900525e-03f;
|
||||
fResult *= fASqr;
|
||||
fResult += 2.45650893e-02f;
|
||||
fResult *= fASqr;
|
||||
fResult += 5.33740603e-02f;
|
||||
fResult *= fASqr;
|
||||
fResult += 1.333923995e-01f;
|
||||
fResult *= fASqr;
|
||||
fResult += 3.333314036e-01f;
|
||||
fResult *= fASqr;
|
||||
fResult += 1.0f;
|
||||
fResult *= val;
|
||||
|
||||
return fResult;
|
||||
|
||||
}
|
||||
|
||||
float fast_asin(float val)
|
||||
{
|
||||
float fRoot = sqrt(1.0f-val);
|
||||
float fResult = -0.0187293f;
|
||||
fResult *= val;
|
||||
fResult += 0.0742610f;
|
||||
fResult *= val;
|
||||
fResult -= 0.2121144f;
|
||||
fResult *= val;
|
||||
fResult += 1.5707288f;
|
||||
fResult = SGD_PI_2 - fRoot*fResult;
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
float fast_acos(float val)
|
||||
{
|
||||
float fRoot = sqrt(1.0f-val);
|
||||
float fResult = -0.0187293f;
|
||||
fResult *= val;
|
||||
fResult += 0.0742610f;
|
||||
fResult *= val;
|
||||
fResult -= 0.2121144f;
|
||||
fResult *= val;
|
||||
fResult += 1.5707288f;
|
||||
fResult *= fRoot;
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
float fast_atan(float val)
|
||||
{
|
||||
float fVSqr = val*val;
|
||||
float fResult = 0.0028662257f;
|
||||
fResult *= fVSqr;
|
||||
fResult -= 0.0161657367f;
|
||||
fResult *= fVSqr;
|
||||
fResult += 0.0429096138f;
|
||||
fResult *= fVSqr;
|
||||
fResult -= 0.0752896400f;
|
||||
fResult *= fVSqr;
|
||||
fResult += 0.1065626393f;
|
||||
fResult *= fVSqr;
|
||||
fResult -= 0.1420889944f;
|
||||
fResult *= fVSqr;
|
||||
fResult += 0.1999355085f;
|
||||
fResult *= fVSqr;
|
||||
fResult -= 0.3333314528f;
|
||||
fResult *= fVSqr;
|
||||
fResult += 1.0f;
|
||||
fResult *= val;
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
@@ -32,24 +32,41 @@
|
||||
|
||||
|
||||
double fast_exp(double val);
|
||||
double fast_exp2(const double val);
|
||||
|
||||
float fast_pow(const float val1, const float val2);
|
||||
float fast_log2(const float cal);
|
||||
float fast_root(const float f, const int n);
|
||||
|
||||
float _fast_pow2(const float cal);
|
||||
float _fast_log2(const float val);
|
||||
|
||||
float fast_sin(const float val);
|
||||
float fast_cos(const float val);
|
||||
float fast_tan(const float val);
|
||||
float fast_asin(const float val);
|
||||
float fast_acos(const float val);
|
||||
float fast_atan(const float val);
|
||||
|
||||
void fast_BSL(float &x, register unsigned long shiftAmount);
|
||||
void fast_BSR(float &x, register unsigned long shiftAmount);
|
||||
|
||||
|
||||
inline float fast_log2 (float val)
|
||||
{
|
||||
int * const exp_ptr = reinterpret_cast <int *> (&val);
|
||||
int x = *exp_ptr;
|
||||
const int log_2 = ((x >> 23) & 255) - 128;
|
||||
x &= ~(255 << 23);
|
||||
x += 127 << 23;
|
||||
*exp_ptr = x;
|
||||
int * const exp_ptr = reinterpret_cast <int *> (&val);
|
||||
int x = *exp_ptr;
|
||||
const int log_2 = ((x >> 23) & 255) - 128;
|
||||
x &= ~(255 << 23);
|
||||
x += 127 << 23;
|
||||
*exp_ptr = x;
|
||||
|
||||
val = ((-1.0f/3) * val + 2) * val - 2.0f/3; // (1)
|
||||
val = ((-1.0f/3) * val + 2) * val - 2.0f/3; // (1)
|
||||
|
||||
return (val + log_2);
|
||||
return (val + log_2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function is about 3 times faster than the system log() function
|
||||
* and has an error of about 0.01%
|
||||
@@ -65,5 +82,36 @@ inline float fast_log10 (const float &val)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function is about twice as fast as the system pow(x,y) function
|
||||
*/
|
||||
inline float fast_pow(const float val1, const float val2)
|
||||
{
|
||||
return _fast_pow2(val2 * _fast_log2(val1));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Haven't seen this elsewhere, probably because it is too obvious?
|
||||
* Anyway, these functions are intended for 32-bit floating point numbers
|
||||
* only and should work a bit faster than the regular ones.
|
||||
*/
|
||||
inline float fast_abs(float f)
|
||||
{
|
||||
int i=((*(int*)&f)&0x7fffffff);
|
||||
return (*(float*)&i);
|
||||
}
|
||||
|
||||
inline float fast_neg(float f)
|
||||
{
|
||||
int i=((*(int*)&f)^0x80000000);
|
||||
return (*(float*)&i);
|
||||
}
|
||||
|
||||
inline int fast_sgn(float f)
|
||||
{
|
||||
return 1+(((*(int*)&f)>>31)<<1);
|
||||
}
|
||||
|
||||
#endif // !_SG_FMATH_HXX
|
||||
|
||||
|
||||
@@ -1,167 +1,212 @@
|
||||
// sg_geodesy.cxx -- routines to convert between geodetic and geocentric
|
||||
// coordinate systems.
|
||||
//
|
||||
// Copied and adapted directly from LaRCsim/ls_geodesy.c
|
||||
//
|
||||
// See below for the complete original LaRCsim comments.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#ifdef SG_HAVE_STD_INCLUDES
|
||||
# include <cmath>
|
||||
# include <cerrno>
|
||||
# include <cstdio>
|
||||
#else
|
||||
# include <math.h>
|
||||
# include <errno.h>
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "point3d.hxx"
|
||||
#include "sg_geodesy.hxx"
|
||||
#include "localconsts.hxx"
|
||||
|
||||
|
||||
SG_USING_STD(cout);
|
||||
|
||||
|
||||
// #define DOMAIN_ERR_DEBUG 1
|
||||
|
||||
|
||||
// sgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
|
||||
// INPUTS:
|
||||
// lat_geoc Geocentric latitude, radians, + = North
|
||||
// radius C.G. radius to earth center (meters)
|
||||
// Notes:
|
||||
//
|
||||
// OUTPUTS:
|
||||
// lat_geod Geodetic latitude, radians, + = North
|
||||
// alt C.G. altitude above mean sea level (meters)
|
||||
// sea_level_r radius from earth center to sea level at
|
||||
// local vertical (surface normal) of C.G. (meters)
|
||||
// The XYZ/cartesian coordinate system in use puts the X axis through
|
||||
// zero lat/lon (off west Africa), the Z axis through the north pole,
|
||||
// and the Y axis through 90 degrees longitude (in the Indian Ocean).
|
||||
//
|
||||
// All latitude and longitude values are in radians. Altitude is in
|
||||
// meters, with zero on the WGS84 ellipsoid.
|
||||
//
|
||||
// The code below makes use of the notion of "squashed" space. This
|
||||
// is a 2D cylindrical coordinate system where the radius from the Z
|
||||
// axis is multiplied by SQUASH; the earth in this space is a perfect
|
||||
// circle with a radius of POLRAD.
|
||||
//
|
||||
// Performance: with full optimization, a transformation from
|
||||
// lat/lon/alt to XYZ and back takes 5263 CPU cycles on my 2.2GHz
|
||||
// Pentium 4. About 83% of this is spent in the iterative sgCartToGeod()
|
||||
// algorithm.
|
||||
|
||||
// These are hard numbers from the WGS84 standard. DON'T MODIFY
|
||||
// unless you want to change the datum.
|
||||
static const double EQURAD = 6378137;
|
||||
static const double iFLATTENING = 298.257223563;
|
||||
|
||||
void sgGeocToGeod( const double& lat_geoc, const double& radius,
|
||||
double *lat_geod, double *alt, double *sea_level_r )
|
||||
// These are derived quantities more useful to the code:
|
||||
#if 0
|
||||
static const double SQUASH = 1 - 1/iFLATTENING;
|
||||
static const double STRETCH = 1/SQUASH;
|
||||
static const double POLRAD = EQURAD * SQUASH;
|
||||
#else
|
||||
// High-precision versions of the above produced with an arbitrary
|
||||
// precision calculator (the compiler might lose a few bits in the FPU
|
||||
// operations). These are specified to 81 bits of mantissa, which is
|
||||
// higher than any FPU known to me:
|
||||
static const double SQUASH = 0.9966471893352525192801545;
|
||||
static const double STRETCH = 1.0033640898209764189003079;
|
||||
static const double POLRAD = 6356752.3142451794975639668;
|
||||
#endif
|
||||
|
||||
// Returns a "local" geodetic latitude: an approximation that will be
|
||||
// correct only at zero altitude.
|
||||
static double localLat(double r, double z)
|
||||
{
|
||||
#ifdef DOMAIN_ERR_DEBUG
|
||||
errno = 0; // start with error zero'd
|
||||
#endif
|
||||
|
||||
double t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
|
||||
double sin_mu_a, denom,delt_lambda, lambda_sl, sin_lambda_sl;
|
||||
|
||||
if( ( (SGD_PI_2 - lat_geoc) < SG_ONE_SECOND ) // near North pole
|
||||
|| ( (SGD_PI_2 + lat_geoc) < SG_ONE_SECOND ) ) // near South pole
|
||||
{
|
||||
*lat_geod = lat_geoc;
|
||||
*sea_level_r = SG_EQUATORIAL_RADIUS_M*E;
|
||||
*alt = radius - *sea_level_r;
|
||||
} else {
|
||||
// cout << " lat_geoc = " << lat_geoc << endl;
|
||||
t_lat = tan(lat_geoc);
|
||||
// cout << " tan(t_lat) = " << t_lat << endl;
|
||||
x_alpha = E*SG_EQUATORIAL_RADIUS_M/sqrt(t_lat*t_lat + E*E);
|
||||
#ifdef DOMAIN_ERR_DEBUG
|
||||
if ( errno ) {
|
||||
perror("fgGeocToGeod()");
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "sqrt(" << t_lat*t_lat + E*E << ")" );
|
||||
}
|
||||
#endif
|
||||
// cout << " x_alpha = " << x_alpha << endl;
|
||||
double tmp = sqrt(SG_EQ_RAD_SQUARE_M - x_alpha * x_alpha);
|
||||
if ( tmp < 0.0 ) { tmp = 0.0; }
|
||||
#ifdef DOMAIN_ERR_DEBUG
|
||||
if ( errno ) {
|
||||
perror("fgGeocToGeod()");
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "sqrt(" << SG_EQ_RAD_SQUARE_M - x_alpha * x_alpha
|
||||
<< ")" );
|
||||
}
|
||||
#endif
|
||||
mu_alpha = atan2(tmp,E*x_alpha);
|
||||
if (lat_geoc < 0) mu_alpha = - mu_alpha;
|
||||
sin_mu_a = sin(mu_alpha);
|
||||
delt_lambda = mu_alpha - lat_geoc;
|
||||
r_alpha = x_alpha/cos(lat_geoc);
|
||||
l_point = radius - r_alpha;
|
||||
*alt = l_point*cos(delt_lambda);
|
||||
|
||||
denom = sqrt(1-EPS*EPS*sin_mu_a*sin_mu_a);
|
||||
#ifdef DOMAIN_ERR_DEBUG
|
||||
if ( errno ) {
|
||||
perror("fgGeocToGeod()");
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "sqrt(" <<
|
||||
1-EPS*EPS*sin_mu_a*sin_mu_a << ")" );
|
||||
}
|
||||
#endif
|
||||
rho_alpha = SG_EQUATORIAL_RADIUS_M*(1-EPS)/
|
||||
(denom*denom*denom);
|
||||
delt_mu = atan2(l_point*sin(delt_lambda),rho_alpha + *alt);
|
||||
*lat_geod = mu_alpha - delt_mu;
|
||||
lambda_sl = atan( E*E * tan(*lat_geod) ); // SL geoc. latitude
|
||||
sin_lambda_sl = sin( lambda_sl );
|
||||
*sea_level_r =
|
||||
sqrt(SG_EQ_RAD_SQUARE_M / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
|
||||
#ifdef DOMAIN_ERR_DEBUG
|
||||
if ( errno ) {
|
||||
perror("fgGeocToGeod()");
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "sqrt(" <<
|
||||
SG_EQ_RAD_SQUARE_M / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl)
|
||||
<< ")" );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Squash to a spherical earth, compute a tangent vector to the
|
||||
// surface circle (in squashed space, the surface is a perfect
|
||||
// sphere) by swapping the components and negating one, stretch to
|
||||
// real coordinates, and take an inverse-tangent/perpedicular
|
||||
// vector to get a local geodetic "up" vector. (Those steps all
|
||||
// cook down to just a few multiplies). Then just turn it into an
|
||||
// angle.
|
||||
double upr = r * SQUASH;
|
||||
double upz = z * STRETCH;
|
||||
return atan2(upz, upr);
|
||||
}
|
||||
|
||||
|
||||
// sgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
|
||||
// INPUTS:
|
||||
// lat_geod Geodetic latitude, radians, + = North
|
||||
// alt C.G. altitude above mean sea level (meters)
|
||||
//
|
||||
// OUTPUTS:
|
||||
// sl_radius SEA LEVEL radius to earth center (meters)
|
||||
// (add Altitude to get true distance from earth center.
|
||||
// lat_geoc Geocentric latitude, radians, + = North
|
||||
//
|
||||
|
||||
|
||||
void sgGeodToGeoc( const double& lat_geod, const double& alt, double *sl_radius,
|
||||
double *lat_geoc )
|
||||
// This is the inverse of the algorithm in localLat(). It returns the
|
||||
// (cylindrical) coordinates of a surface latitude expressed as an
|
||||
// "up" unit vector.
|
||||
static void surfRZ(double upr, double upz, double* r, double* z)
|
||||
{
|
||||
double lambda_sl, sin_lambda_sl, cos_lambda_sl, sin_mu, cos_mu, px, py;
|
||||
|
||||
#ifdef DOMAIN_ERR_DEBUG
|
||||
errno = 0;
|
||||
#endif
|
||||
// We are
|
||||
// converting a (2D, cylindrical) "up" vector defined by the
|
||||
// geodetic latitude into unitless R and Z coordinates in
|
||||
// cartesian space.
|
||||
double R = upr * STRETCH;
|
||||
double Z = upz * SQUASH;
|
||||
|
||||
lambda_sl = atan( E*E * tan(lat_geod) ); // sea level geocentric latitude
|
||||
sin_lambda_sl = sin( lambda_sl );
|
||||
cos_lambda_sl = cos( lambda_sl );
|
||||
sin_mu = sin(lat_geod); // Geodetic (map makers') latitude
|
||||
cos_mu = cos(lat_geod);
|
||||
*sl_radius =
|
||||
sqrt(SG_EQ_RAD_SQUARE_M / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
|
||||
#ifdef DOMAIN_ERR_DEBUG
|
||||
if ( errno ) {
|
||||
perror("fgGeodToGeoc()");
|
||||
SG_LOG( SG_GENERAL, SG_ALERT, "sqrt(" <<
|
||||
SG_EQ_RAD_SQUARE_M / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl)
|
||||
<< ")" );
|
||||
}
|
||||
#endif
|
||||
py = *sl_radius*sin_lambda_sl + alt*sin_mu;
|
||||
px = *sl_radius*cos_lambda_sl + alt*cos_mu;
|
||||
*lat_geoc = atan2( py, px );
|
||||
// Now we need to turn R and Z into a surface point. That is,
|
||||
// pick a coefficient C for them such that the point is on the
|
||||
// surface when converted to "squashed" space:
|
||||
// (C*R*SQUASH)^2 + (C*Z)^2 = POLRAD^2
|
||||
// C^2 = POLRAD^2 / ((R*SQUASH)^2 + Z^2)
|
||||
double sr = R * SQUASH;
|
||||
double c = POLRAD / sqrt(sr*sr + Z*Z);
|
||||
R *= c;
|
||||
Z *= c;
|
||||
|
||||
*r = R; *z = Z;
|
||||
}
|
||||
|
||||
// Returns the insersection of the line joining the center of the
|
||||
// earth and the specified cylindrical point with the surface of the
|
||||
// WGS84 ellipsoid. Works by finding a normalization constant (in
|
||||
// squashed space) that places the squashed point on the surface of
|
||||
// the sphere.
|
||||
static double seaLevelRadius(double r, double z)
|
||||
{
|
||||
double sr = r * SQUASH;
|
||||
double norm = POLRAD/sqrt(sr*sr + z*z);
|
||||
r *= norm;
|
||||
z *= norm;
|
||||
return sqrt(r*r + z*z);
|
||||
}
|
||||
|
||||
// Convert a cartexian XYZ coordinate to a geodetic lat/lon/alt. This
|
||||
// is a "recursion relation". In essence, it iterates over the 2D
|
||||
// part of sgGeodToCart refining its approximation at each step. The
|
||||
// MAX_LAT_ERROR threshold is picked carefully to allow us to reach
|
||||
// the full precision of an IEEE double. While this algorithm might
|
||||
// look slow, it's not. It actually converges very fast indeed --
|
||||
// I've never seen it take more than six iterations under normal
|
||||
// conditions. Three or four is more typical. (It gets slower as the
|
||||
// altitude/error gets larger; at 50000m altitude, it starts to need
|
||||
// seven loops.) One caveat is that at *very* large altitudes, it
|
||||
// starts making very poor guesses as to latitude. As altitude
|
||||
// approaches infinity, it should be guessing with geocentric
|
||||
// coordinates, not "local geodetic up" ones.
|
||||
void sgCartToGeod(const double* xyz, double* lat, double* lon, double* alt)
|
||||
{
|
||||
// The error is expressed as a radian angle, and we want accuracy
|
||||
// to 1 part in 2^50 (an IEEE double has between 51 and 52
|
||||
// significant bits of magnitude due to the "hidden" digit; leave
|
||||
// at least one bit free for potential slop). In real units, this
|
||||
// works out to about 6 nanometers.
|
||||
static const double MAX_LAT_ERROR = 8.881784197001252e-16;
|
||||
double x = xyz[0], y = xyz[1], z = xyz[2];
|
||||
|
||||
// Longitude is trivial. Convert to cylindrical "(r, z)"
|
||||
// coordinates while we're at it.
|
||||
*lon = atan2(y, x);
|
||||
double r = sqrt(x*x + y*y);
|
||||
|
||||
double lat1, lat2 = localLat(r, z);
|
||||
double r2, z2, dot;
|
||||
do {
|
||||
lat1 = lat2;
|
||||
|
||||
// Compute an "up" vector
|
||||
double upr = cos(lat1);
|
||||
double upz = sin(lat1);
|
||||
|
||||
// Find the surface point with that latitude
|
||||
surfRZ(upr, upz, &r2, &z2);
|
||||
|
||||
// Convert r2z2 to the vector pointing from the surface to rz
|
||||
r2 = r - r2;
|
||||
z2 = z - z2;
|
||||
|
||||
// Dot it with "up" to get an approximate altitude
|
||||
dot = r2*upr + z2*upz;
|
||||
|
||||
// And compute an approximate geodetic surface coordinate
|
||||
// using that altitude, so now: R2Z2 = RZ - ((RZ - SURF) dot
|
||||
// UP)
|
||||
r2 = r - dot * upr;
|
||||
z2 = z - dot * upz;
|
||||
|
||||
// Find the latitude of *that* point, and iterate
|
||||
lat2 = localLat(r2, z2);
|
||||
} while(fabs(lat2 - lat1) > MAX_LAT_ERROR);
|
||||
|
||||
// All done! We have an accurate geodetic lattitude, now
|
||||
// calculate the altitude as a cartesian distance between the
|
||||
// final geodetic surface point and the initial r/z coordinate.
|
||||
*lat = lat1;
|
||||
double dr = r - r2;
|
||||
double dz = z - z2;
|
||||
double altsign = (dot > 0) ? 1 : -1;
|
||||
*alt = altsign * sqrt(dr*dr + dz*dz);
|
||||
}
|
||||
|
||||
void sgGeodToCart(double lat, double lon, double alt, double* xyz)
|
||||
{
|
||||
// This is the inverse of the algorithm in localLat(). We are
|
||||
// converting a (2D, cylindrical) "up" vector defined by the
|
||||
// geodetic latitude into unitless R and Z coordinates in
|
||||
// cartesian space.
|
||||
double upr = cos(lat);
|
||||
double upz = sin(lat);
|
||||
double r, z;
|
||||
surfRZ(upr, upz, &r, &z);
|
||||
|
||||
// Add the altitude using the "up" unit vector we calculated
|
||||
// initially.
|
||||
r += upr * alt;
|
||||
z += upz * alt;
|
||||
|
||||
// Finally, convert from cylindrical to cartesian
|
||||
xyz[0] = r * cos(lon);
|
||||
xyz[1] = r * sin(lon);
|
||||
xyz[2] = z;
|
||||
}
|
||||
|
||||
void sgGeocToGeod(double lat_geoc, double radius,
|
||||
double *lat_geod, double *alt, double *sea_level_r)
|
||||
{
|
||||
// Build a fake cartesian point, and run it through CartToGeod
|
||||
double lon_dummy, xyz[3];
|
||||
xyz[0] = cos(lat_geoc) * radius;
|
||||
xyz[1] = 0;
|
||||
xyz[2] = sin(lat_geoc) * radius;
|
||||
sgCartToGeod(xyz, lat_geod, &lon_dummy, alt);
|
||||
*sea_level_r = seaLevelRadius(xyz[0], xyz[2]);
|
||||
}
|
||||
|
||||
void sgGeodToGeoc(double lat_geod, double alt,
|
||||
double *sl_radius, double *lat_geoc)
|
||||
{
|
||||
double xyz[3];
|
||||
sgGeodToCart(lat_geod, 0, alt, xyz);
|
||||
*lat_geoc = atan2(xyz[2], xyz[0]);
|
||||
*sl_radius = seaLevelRadius(xyz[0], xyz[2]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Direct and inverse distance functions
|
||||
//
|
||||
// Proceedings of the 7th International Symposium on Geodetic
|
||||
@@ -175,13 +220,11 @@ void sgGeodToGeoc( const double& lat_geod, const double& alt, double *sl_radius,
|
||||
//
|
||||
// modified for FlightGear to use WGS84 only -- Norman Vine
|
||||
|
||||
#define GEOD_INV_PI SGD_PI
|
||||
static const double GEOD_INV_PI = SGD_PI;
|
||||
|
||||
// s == distance
|
||||
// az = azimuth
|
||||
|
||||
// for WGS_84 a = 6378137.000, rf = 298.257223563;
|
||||
|
||||
static inline double M0( double e2 ) {
|
||||
//double e4 = e2*e2;
|
||||
return GEOD_INV_PI*(1.0 - e2*( 1.0/4.0 + e2*( 3.0/64.0 +
|
||||
@@ -191,12 +234,12 @@ static inline double M0( double e2 ) {
|
||||
|
||||
// given, alt, lat1, lon1, az1 and distance (s), calculate lat2, lon2
|
||||
// and az2. Lat, lon, and azimuth are in degrees. distance in meters
|
||||
int geo_direct_wgs_84 ( const double& alt, const double& lat1,
|
||||
const double& lon1, const double& az1,
|
||||
const double& s, double *lat2, double *lon2,
|
||||
int geo_direct_wgs_84 ( double alt, double lat1,
|
||||
double lon1, double az1,
|
||||
double s, double *lat2, double *lon2,
|
||||
double *az2 )
|
||||
{
|
||||
double a = 6378137.000, rf = 298.257223563;
|
||||
double a = EQURAD, rf = iFLATTENING;
|
||||
double RADDEG = (GEOD_INV_PI)/180.0, testv = 1.0E-10;
|
||||
double f = ( rf > 0.0 ? 1.0/rf : 0.0 );
|
||||
double b = a*(1.0-f);
|
||||
@@ -284,12 +327,12 @@ int geo_direct_wgs_84 ( const double& alt, const double& lat1,
|
||||
// given alt, lat1, lon1, lat2, lon2, calculate starting and ending
|
||||
// az1, az2 and distance (s). Lat, lon, and azimuth are in degrees.
|
||||
// distance in meters
|
||||
int geo_inverse_wgs_84( const double& alt, const double& lat1,
|
||||
const double& lon1, const double& lat2,
|
||||
const double& lon2, double *az1, double *az2,
|
||||
int geo_inverse_wgs_84( double alt, double lat1,
|
||||
double lon1, double lat2,
|
||||
double lon2, double *az1, double *az2,
|
||||
double *s )
|
||||
{
|
||||
double a = 6378137.000, rf = 298.257223563;
|
||||
double a = EQURAD, rf = iFLATTENING;
|
||||
int iter=0;
|
||||
double RADDEG = (GEOD_INV_PI)/180.0, testv = 1.0E-10;
|
||||
double f = ( rf > 0.0 ? 1.0/rf : 0.0 );
|
||||
@@ -399,92 +442,3 @@ int geo_inverse_wgs_84( const double& alt, const double& lat1,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
TITLE: ls_geodesy
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
FUNCTION: Converts geocentric coordinates to geodetic positions
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
MODULE STATUS: developmental
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
GENEALOGY: Written as part of LaRCSim project by E. B. Jackson
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
DESIGNED BY: E. B. Jackson
|
||||
|
||||
CODED BY: E. B. Jackson
|
||||
|
||||
MAINTAINED BY: E. B. Jackson
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
MODIFICATION HISTORY:
|
||||
|
||||
DATE PURPOSE BY
|
||||
|
||||
930208 Modified to avoid singularity near polar region. EBJ
|
||||
930602 Moved backwards calcs here from ls_step. EBJ
|
||||
931214 Changed erroneous Latitude and Altitude variables to
|
||||
*lat_geod and *alt in routine ls_geoc_to_geod. EBJ
|
||||
940111 Changed header files from old ls_eom.h style to ls_types,
|
||||
and ls_constants. Also replaced old DATA type with new
|
||||
SCALAR type. EBJ
|
||||
|
||||
CURRENT RCS HEADER:
|
||||
|
||||
$Header$
|
||||
* Revision 1.5 1994/01/11 18:47:05 bjax
|
||||
* Changed include files to use types and constants, not ls_eom.h
|
||||
* Also changed DATA type to SCALAR type.
|
||||
*
|
||||
* Revision 1.4 1993/12/14 21:06:47 bjax
|
||||
* Removed global variable references Altitude and Latitude. EBJ
|
||||
*
|
||||
* Revision 1.3 1993/06/02 15:03:40 bjax
|
||||
* Made new subroutine for calculating geodetic to geocentric; changed name
|
||||
* of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
|
||||
*
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
REFERENCES:
|
||||
|
||||
[ 1] Stevens, Brian L.; and Lewis, Frank L.: "Aircraft
|
||||
Control and Simulation", Wiley and Sons, 1992.
|
||||
ISBN 0-471-61397-5
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
CALLED BY: ls_aux
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
CALLS TO:
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
INPUTS:
|
||||
lat_geoc Geocentric latitude, radians, + = North
|
||||
radius C.G. radius to earth center, ft
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
OUTPUTS:
|
||||
lat_geod Geodetic latitude, radians, + = North
|
||||
alt C.G. altitude above mean sea level, ft
|
||||
sea_level_r radius from earth center to sea level at
|
||||
local vertical (surface normal) of C.G.
|
||||
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +1,7 @@
|
||||
/**
|
||||
* \file sg_geodesy.hxx
|
||||
* Routines to convert between geodetic and geocentric coordinate systems.
|
||||
* Copied and adapted directly from LaRCsim/ls_geodesy.c
|
||||
*/
|
||||
|
||||
// See below for the complete original LaRCsim comments.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _SG_GEODESY_HXX
|
||||
#define _SG_GEODESY_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
|
||||
|
||||
/**
|
||||
* Convert from geocentric coordinates to geodetic coordinates
|
||||
@@ -31,45 +12,78 @@
|
||||
* @param sea_level_r (out) radius from earth center to sea level at
|
||||
* local vertical (surface normal) of C.G. (meters)
|
||||
*/
|
||||
void sgGeocToGeod( const double& lat_geoc, const double& radius,
|
||||
double *lat_geod, double *alt, double *sea_level_r );
|
||||
void sgGeocToGeod(double lat_geoc, double radius,
|
||||
double *lat_geod, double *alt, double *sea_level_r);
|
||||
|
||||
|
||||
/**
|
||||
* Convert from geodetic coordinates to geocentric coordinates
|
||||
* Convert from geodetic coordinates to geocentric coordinates.
|
||||
* WARNING: this function is non-reversible. Due to the fact that
|
||||
* "up" is a different direction for geocentric and geodetic frames,
|
||||
* you can not simply add your "alt" parameter to the "sl_radius"
|
||||
* result and get back (via sgGeodToGeoc()) to the coordinates you
|
||||
* started with. The error under normal conditions will be of
|
||||
* centimeter order; whether that is important or not is application
|
||||
* dependent. Consider using sgGeodToCart() instead.
|
||||
*
|
||||
* @param lat_geod (in) Geodetic latitude, radians, + = North
|
||||
* @param alt (in) C.G. altitude above mean sea level (meters)
|
||||
* @param sl_radius (out) SEA LEVEL radius to earth center (meters)
|
||||
* (add Altitude to get true distance from earth center.
|
||||
* @param lat_geoc (out) Geocentric latitude, radians, + = North
|
||||
*/
|
||||
void sgGeodToGeoc( const double& lat_geod, const double& alt,
|
||||
double *sl_radius, double *lat_geoc );
|
||||
void sgGeodToGeoc(double lat_geod, double alt,
|
||||
double *sl_radius, double *lat_geoc );
|
||||
|
||||
/**
|
||||
* Convert a cartesian point to a geodetic lat/lon/altitude.
|
||||
*
|
||||
* @param xyz (in) Pointer to cartesian point.
|
||||
* @param lat (out) Latitude, in radians
|
||||
* @param lon (out) Longitude, in radians
|
||||
* @param alt (out) Altitude, in meters above the WGS84 ellipsoid
|
||||
*/
|
||||
void sgCartToGeod(const double* xyz, double* lat, double* lon, double* alt);
|
||||
|
||||
/**
|
||||
* Convert a cartesian point to a geodetic lat/lon/altitude.
|
||||
* Alternate form using Point3D objects.
|
||||
*
|
||||
* @param cartesian point
|
||||
* @return geodetic point
|
||||
*/
|
||||
inline Point3D sgCartToGeod(const Point3D& p)
|
||||
{
|
||||
double lat, lon, alt, xyz[3];
|
||||
xyz[0] = p.x(); xyz[1] = p.y(); xyz[2] = p.z();
|
||||
sgCartToGeod(xyz, &lat, &lon, &alt);
|
||||
return Point3D(lon, lat, alt);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a geodetic point lon(radians), lat(radians), elev(meter) to
|
||||
* a cartesian point.
|
||||
* Convert a geodetic lat/lon/altitude to a cartesian point.
|
||||
*
|
||||
* @param lat (in) Latitude, in radians
|
||||
* @param lon (in) Longitude, in radians
|
||||
* @param alt (in) Altitude, in meters above the WGS84 ellipsoid
|
||||
* @param xyz (out) Pointer to cartesian point.
|
||||
*/
|
||||
void sgGeodToCart(double lat, double lon, double alt, double* xyz);
|
||||
|
||||
/**
|
||||
* Convert a geodetic lat/lon/altitude to a cartesian point.
|
||||
* Alternate form using Point3D objects.
|
||||
*
|
||||
* @param geodetic point
|
||||
* @return cartesian point
|
||||
*/
|
||||
inline Point3D sgGeodToCart(const Point3D& geod) {
|
||||
double gc_lon, gc_lat, sl_radius;
|
||||
|
||||
// printf("A geodetic point is (%.2f, %.2f, %.2f)\n",
|
||||
// geod[0], geod[1], geod[2]);
|
||||
|
||||
gc_lon = geod.lon();
|
||||
sgGeodToGeoc(geod.lat(), geod.radius(), &sl_radius, &gc_lat);
|
||||
|
||||
// printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon,
|
||||
// gc_lat, sl_radius+geod[2]);
|
||||
|
||||
Point3D pp = Point3D( gc_lon, gc_lat, sl_radius + geod.radius());
|
||||
return sgPolarToCart3d(pp);
|
||||
inline Point3D sgGeodToCart(const Point3D& geod)
|
||||
{
|
||||
double xyz[3];
|
||||
sgGeodToCart(geod.lat(), geod.lon(), geod.elev(), xyz);
|
||||
return Point3D(xyz[0], xyz[1], xyz[2]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a starting position and an offset radial and distance,
|
||||
* calculate an ending positon on a wgs84 ellipsoid.
|
||||
@@ -82,9 +96,9 @@ inline Point3D sgGeodToCart(const Point3D& geod) {
|
||||
* @param lon2 (out) degrees
|
||||
* @param az2 (out) return course in degrees
|
||||
*/
|
||||
int geo_direct_wgs_84 ( const double& alt, const double& lat1,
|
||||
const double& lon1, const double& az1,
|
||||
const double& s, double *lat2, double *lon2,
|
||||
int geo_direct_wgs_84 ( double alt, double lat1,
|
||||
double lon1, double az1,
|
||||
double s, double *lat2, double *lon2,
|
||||
double *az2 );
|
||||
|
||||
|
||||
@@ -100,98 +114,9 @@ int geo_direct_wgs_84 ( const double& alt, const double& lat1,
|
||||
* @param az2 (out) end heading degrees
|
||||
* @param s (out) distance meters
|
||||
*/
|
||||
int geo_inverse_wgs_84( const double& alt, const double& lat1,
|
||||
const double& lon1, const double& lat2,
|
||||
const double& lon2, double *az1, double *az2,
|
||||
int geo_inverse_wgs_84( double alt, double lat1,
|
||||
double lon1, double lat2,
|
||||
double lon2, double *az1, double *az2,
|
||||
double *s );
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
TITLE: ls_geodesy
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
FUNCTION: Converts geocentric coordinates to geodetic positions
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
MODULE STATUS: developmental
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
GENEALOGY: Written as part of LaRCSim project by E. B. Jackson
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
DESIGNED BY: E. B. Jackson
|
||||
|
||||
CODED BY: E. B. Jackson
|
||||
|
||||
MAINTAINED BY: E. B. Jackson
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
MODIFICATION HISTORY:
|
||||
|
||||
DATE PURPOSE BY
|
||||
|
||||
930208 Modified to avoid singularity near polar region. EBJ
|
||||
930602 Moved backwards calcs here from ls_step. EBJ
|
||||
931214 Changed erroneous Latitude and Altitude variables to
|
||||
*lat_geod and *alt in routine ls_geoc_to_geod. EBJ
|
||||
940111 Changed header files from old ls_eom.h style to ls_types,
|
||||
and ls_constants. Also replaced old DATA type with new
|
||||
SCALAR type. EBJ
|
||||
|
||||
CURRENT RCS HEADER:
|
||||
|
||||
$Header$
|
||||
|
||||
* Revision 1.5 1994/01/11 18:47:05 bjax
|
||||
* Changed include files to use types and constants, not ls_eom.h
|
||||
* Also changed DATA type to SCALAR type.
|
||||
*
|
||||
* Revision 1.4 1993/12/14 21:06:47 bjax
|
||||
* Removed global variable references Altitude and Latitude. EBJ
|
||||
*
|
||||
* Revision 1.3 1993/06/02 15:03:40 bjax
|
||||
* Made new subroutine for calculating geodetic to geocentric; changed name
|
||||
* of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
|
||||
*
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
REFERENCES:
|
||||
|
||||
[ 1] Stevens, Brian L.; and Lewis, Frank L.: "Aircraft
|
||||
Control and Simulation", Wiley and Sons, 1992.
|
||||
ISBN 0-471-61397-5
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
CALLED BY: ls_aux
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
CALLS TO:
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
INPUTS:
|
||||
lat_geoc Geocentric latitude, radians, + = North
|
||||
radius C.G. radius to earth center, ft
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
OUTPUTS:
|
||||
lat_geod Geodetic latitude, radians, + = North
|
||||
alt C.G. altitude above mean sea level, ft
|
||||
sea_level_r radius from earth center to sea level at
|
||||
local vertical (surface normal) of C.G.
|
||||
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#endif // _SG_GEODESY_HXX
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* Title: antoi */
|
||||
/* Date: Jan 28, 1991 */
|
||||
/* Organization: W/OSO242 - Graphics and Display Section */
|
||||
/* Programmer: Allan Darling */
|
||||
/* Language: C/370 */
|
||||
/* */
|
||||
/* Abstract: This function will convert a character array */
|
||||
/* (string) of length (len) into an integer. */
|
||||
/* The integer is created via a call to the */
|
||||
/* function atoi. This function extends the */
|
||||
/* functionality of atoi by removing the */
|
||||
/* requirement for a sentinal delimited string */
|
||||
/* as input. */
|
||||
/* */
|
||||
/* Input: - Pointer to an array of characters. */
|
||||
/* - Integer indicating the number of character to include */
|
||||
/* in the conversion. */
|
||||
/* */
|
||||
/* Output:- An integer corresponding to the value in the character */
|
||||
/* array or INT32_MIN (-2147483647-1) if the function is */
|
||||
/* unable to acquire system storage. */
|
||||
/* */
|
||||
/* Modification History: */
|
||||
/* None */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MIN
|
||||
# define INT32_MIN (-2147483647-1)
|
||||
#endif
|
||||
|
||||
int antoi(char * string, int len)
|
||||
{
|
||||
|
||||
/*******************/
|
||||
/* local variables */
|
||||
/*******************/
|
||||
|
||||
char * tmpstr;
|
||||
int i,
|
||||
retval;
|
||||
|
||||
|
||||
/*****************/
|
||||
/* function body */
|
||||
/*****************/
|
||||
|
||||
tmpstr = (char *)malloc((len+1) * sizeof(char));
|
||||
|
||||
if (tmpstr == NULL) return INT32_MIN;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
tmpstr[i] = string[i];
|
||||
|
||||
tmpstr[len] = '\0';
|
||||
|
||||
retval = atoi(tmpstr);
|
||||
|
||||
free(tmpstr);
|
||||
|
||||
return(retval);
|
||||
|
||||
} /* end antoi */
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
#include "Local.h" /* standard header file */
|
||||
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* Title: charcmp */
|
||||
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
|
||||
/* Date: 12 Dec 1995 */
|
||||
/* Programmer: CINDY L. CHONG */
|
||||
/* Language: C/370 */
|
||||
/* */
|
||||
/* Abstract: This function will compare each character in the */
|
||||
/* string match with each character in the pattern */
|
||||
/* which is made up of characters. The str can */
|
||||
/* be longer than the pattern. */
|
||||
/* */
|
||||
/* External Functions Called: */
|
||||
/* None. */
|
||||
/* */
|
||||
/* Input: str is a pointer to char */
|
||||
/* pattern is a pointer to char */
|
||||
/* */
|
||||
/* Output: Return true if str matches pattern, */
|
||||
/* otherwise, return false */
|
||||
/* */
|
||||
/* Modification History: */
|
||||
/* None. */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
|
||||
bool charcmp(char *str, char *pattern)
|
||||
{
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
/* Loop while str and pattern is not equal to null, then */
|
||||
/* inscreases str and pattern by one */
|
||||
/**********************************************************/
|
||||
|
||||
for (; *pattern != '\0'; pattern++)
|
||||
{
|
||||
if (*str == '\0')
|
||||
return FALSE;
|
||||
|
||||
/************************************************************/
|
||||
/* If pattern match str, then increase str and jump out the */
|
||||
/* case and read next char of the str and pattern */
|
||||
/************************************************************/
|
||||
|
||||
if ( isspace(*pattern) )
|
||||
pattern = nxtalpha(pattern);
|
||||
|
||||
switch( *pattern )
|
||||
{
|
||||
case 'c':
|
||||
if ( !isalnum(*str++) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if ( !isalpha(*str) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
str++;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if ( !iscntrl(*str++) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if ( !isdigit(*str) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
str++;
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
if ( !isgraph(*str++) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
if ( !islower(*str++) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if ( !isprint(*str++) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if ( !ispunct(*str++) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if ( !isspace(*str++) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
if ( !isupper(*str++) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (*str++ != ' ')
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if ( !isspace(*str) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( isspace(*str) )
|
||||
str++;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
pattern++;
|
||||
if (*pattern != *str)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
pattern++;
|
||||
str++;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
|
||||
} /* end switch */
|
||||
|
||||
} /* end for */
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,539 +0,0 @@
|
||||
#include "Metar.h"
|
||||
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* Title: dRVMETAR */
|
||||
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
|
||||
/* Date: 28 Oct 1994 */
|
||||
/* Programmer: CARL MCCALLA */
|
||||
/* Language: C/370 */
|
||||
/* */
|
||||
/* Abstract: DRVMETAR is a main routine that acts a driver */
|
||||
/* for testing the METAR Decoder function. */
|
||||
/* */
|
||||
/* External Functions Called: */
|
||||
/* None. */
|
||||
/* DcdMETAR */
|
||||
/* prtDcdMetar */
|
||||
/* Sec0MTSm */
|
||||
/* Sec1MTSm */
|
||||
/* */
|
||||
/* Input: None */
|
||||
/* */
|
||||
/* Output: None */
|
||||
/* */
|
||||
/* Modification History: */
|
||||
/* None. */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
int main()
|
||||
{
|
||||
static char *string[] =
|
||||
{
|
||||
"KAST 221156Z COR 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
|
||||
|
||||
"KAST COR 221156Z 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
|
||||
|
||||
"KAST COR 221156Z 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
|
||||
|
||||
"KP88 COR 221156 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
|
||||
|
||||
"KP88 COR 221156 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 6//// 70109 T00890084 10100 20089 55005",
|
||||
|
||||
NULL,
|
||||
|
||||
|
||||
"EPIT 1755 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1/2V3/4",
|
||||
|
||||
"KFAR 181154Z 10003KT 1/4SM HZ CLR 16/13 A2988 RMK AO2 "
|
||||
"SLP117 56012 10345 20226 T01610133 $",
|
||||
|
||||
"KFAR 181154Z 10003KT 1/SM HZ CLR 16/13 A2988 RMK AO2 "
|
||||
"SLP117 56012 10345 20226 T01610133 $",
|
||||
|
||||
|
||||
|
||||
|
||||
"RKSS 21009KT 1400 RP2000 // ////// 21/20 1006/2972 NOSIG",
|
||||
|
||||
"RKSS 1200 21009KT 1400 RP2000 // ////// 21/20 1006/2972 NOSIG",
|
||||
|
||||
"RKSS 1130Z 23011KT 1100 R14R/P1500N R14L/P1500N BR SCT010 BKN030 "
|
||||
"BKN080 21/21 Q1006 NOSIG",
|
||||
|
||||
"RKSS 1130Z 23011KT 1100 R14R/P1500 R14L/P1500 BR SCT010 BKN030 "
|
||||
"BKN080 21/21 Q1006 NOSIG",
|
||||
|
||||
NULL,
|
||||
"KFAR 181154Z 10003KT 4SM HZ CLR 16/13 A2988 RMK AO2 "
|
||||
"SLP117 56012 1//// 2//// T01610133 $",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE DUE LO CLD SLP186",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE DUE10 LO CLD SLP186",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE DUE9 LO CLD SLP186",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE FZDZE10 LO CLD SLP186",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE FZDZE9 LO CLD SLP186",
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 30/XX Q1015",
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 M30/XX Q1015",
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 MM/XX Q1015",
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 MM/30 Q1015",
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 MM/M30 Q1015",
|
||||
|
||||
|
||||
|
||||
|
||||
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 BKN045 OVC090 "
|
||||
"SCT120 FEW250 RMK OCNL LTGICCG OHD",
|
||||
|
||||
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 07/01 Q1011 "
|
||||
"RMK TEMPO 8000 -SHRA BKN015 FRQ LTG VC",
|
||||
|
||||
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 07/01 Q1011 "
|
||||
"RMK TEMPO 8000 -SHRA BKN015 LTG DSNT W",
|
||||
|
||||
|
||||
"METAR KLAX 281156Z AUTO VRB100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC "
|
||||
"+TS BLPY FEW/// SCT000 BKN050 SCT150 OVC250 3/M1 A2991 RMK "
|
||||
"TORNADO B13E45 6 NE MOV E A02 PK WND 18515/45 "
|
||||
"WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"VIS 2 1/2 RY11 "
|
||||
"DVR/1000V1600FT "
|
||||
"OCNL LTG VCY STN "
|
||||
"RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RY11 "
|
||||
"PRESFR PRESRR SLP013 FG FEW/// HZ SCT000 VIS NW 2 1/2 GR 3/4 "
|
||||
"VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC "
|
||||
"FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 "
|
||||
"933125 98096 P 0125 60225 70565 "
|
||||
"T00261015 10369 21026 "
|
||||
"404800360 52101 VISNO RY05 CHINO RY27 PNO RVRNO "
|
||||
"PWINO FZRANO TSNO $",
|
||||
|
||||
|
||||
"KBOS 251356Z 26011KT 10SM CLR 12/02 A2995 RMK AO2 SC VCNTY "
|
||||
"STN SSE-NNW SCT CI ABV SLP141 T01220023",
|
||||
|
||||
"EFHK 36009KT 340V060 CAVOK 12/M02 Q1013 NOSIG",
|
||||
"EGKK 24011KT 210V300 9999 SCT020 BKN045 12/06 Q1007 NOSIG",
|
||||
"EGPD 31018KT 8000 RA FEW013 BKN021 OVC045 06/04 Q0994 NOSIG",
|
||||
"EKCH 16012KT CAVOK 20/07 Q1006 NOSIG",
|
||||
"ESKN 10014KT 9000 BR SCT100 14/04 Q1010",
|
||||
"LOWW 231450Z 14017KT CAVOK 23/07 Q1010 NOSIG",
|
||||
|
||||
|
||||
"METAR CYCH 171500Z CCA 30017KT 2SM -SN BKN006",
|
||||
|
||||
"METAR CYOW 171500Z CCA 30017KT 2SM -SN BKN006 OVC020 00/M02 "
|
||||
"A2957 RMK S35F4NS1 /S01/ SNW WET SNW MELTG ON GRND CIG 5-7 "
|
||||
"SLP018",
|
||||
|
||||
"KAST 221156Z AUTO 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005"
|
||||
" TSB0159E30 TS SE MOV NE",
|
||||
|
||||
"KAST 221156Z AUTO 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005"
|
||||
" TSE0159 TS SE",
|
||||
|
||||
"KHVR 1756Z 31007KT 5SM -SN SCT011 BKN024 OVC030 M05/M08 A3056 "
|
||||
"RMK AOA 933004 "
|
||||
"BKN V SCT TNO PCPN 000 $ SLP389 4/015 60002 "
|
||||
"T10501077 11050 21078 51010",
|
||||
|
||||
"SPECI KGFI 041420Z AUTO 18030KT 3 1/2SM RVRNO TS -RA BKN008 OVC060 "
|
||||
"26/22 A2991 RMK A02 RA15TSB20 PRESFR SLP 101 P 0000 T02640218",
|
||||
|
||||
"METAR KCLE 281156Z 170100G135KT 110V180 M1/4SM "
|
||||
"R01L/P6000FT +TSSHRA VCFG "
|
||||
"BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"CIG 1000V1500 PRESFR FRQ LTG CG NW "
|
||||
"RAB1030E1145 FZDZE56 PRESRR SLP135 GS "
|
||||
"T1263 "
|
||||
"VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"CYQR 161700Z 15015KT 15SM SCT045 SCT090 BKN250 10/03 A2955 "
|
||||
"RMK SC1AC2C11 OB TAKEN H+ 5 DUE AWOS FAILURE SLP027",
|
||||
|
||||
|
||||
|
||||
|
||||
"KPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2",
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 199/182",
|
||||
|
||||
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP701 P0254 199/182",
|
||||
|
||||
"KHLN 281156Z AUTO 27005KT 10SM OVC023 07/05 A3011 RMK AOA OVC V "
|
||||
"BKN $ SLP202 60000 70001 T00670050 10122 20061 53003",
|
||||
|
||||
"KPHX 281156Z 12004KT 10SM CLR 15/05 A2996 RMK AOA SLP135 T01500050 "
|
||||
"10250 20150 53006",
|
||||
"KFCA 281156Z 30003KT 10SM CLR 06/02 A3009 RMK AO TNO $ SLP191 "
|
||||
"T00610023 10167 20056 53003",
|
||||
"KAST 281156Z 00000KT 10SM BKN095 09/08 A2997 RMK AOA SLP150 "
|
||||
"T00940084 10161 20094 52005 ",
|
||||
"KHVR 281156Z 03003KT 10SM OVC020 09/07 A3010 RMK AO TNO ZRNO "
|
||||
"$ SLP194 T00940073 10156 20089 51005",
|
||||
"KGGW 281156Z 35006KT 5SM BR OVC010 10/09 A3003 RMK AOA $ SLP177 "
|
||||
"70003 T01000095 10156 20110 53008",
|
||||
"KELY 1153Z AUTO 14004KT 10SM SCT075 01/M01 A3011 RMK AOA TNO ZRNO "
|
||||
"SLP171 70001 T00061011 10139 21006 51005",
|
||||
"KFLG 281156Z 29006KT 10SM CLR 04/M01 A3012 RMK AO TNO SLP147 "
|
||||
"T00391011 21006 51004",
|
||||
"KGTF 281156Z 27005KT 7SM BKN080 04/04 A3010 RMK AOA SLP205 "
|
||||
"T00440045 10117 20039 51006",
|
||||
|
||||
"K13A 1918Z 20011KT 26/M06 RMK AO PKWND 020/RNO 644V264 T02611061",
|
||||
|
||||
"KP88 1919Z 09001KT 14/03 RMK AO / PKWND 002/RNO 158 Z T01440034",
|
||||
|
||||
"K40B 1924Z 29004KT 15/M07 RMK AO PKWND 011/RM MV263 T01501072",
|
||||
|
||||
"KGGW 1756Z 33018KT 10SM OVC015 M03/M06 A3041 RMK AOA SLP338 "
|
||||
"4/007 60002 T10281055 11028 21072 51009",
|
||||
"KPHX 1756Z 130004KT 10SM CLR 18/M03 A3001 RMK AOA SLP154 "
|
||||
"T01781033 10178 20067 58007",
|
||||
"KFCA 1756Z 29005KT 10SM CLR 05/M11 A3049 RMK AOA TNO SLP352 "
|
||||
"T00501111 10050 21044 50004",
|
||||
"KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 "
|
||||
"T01110045 10111 20000 50002",
|
||||
"KELY 1753Z 34010KT 10SM CLR 01/M07 A3022 RMK AOA TNO ZRNO "
|
||||
"SLP240 T00111066 10011 21078 58007",
|
||||
"KFLG 1756Z 07006KT 10SM CLR 06/M12 A3009 RMK AO TNO ZRNO "
|
||||
"SLP178 T00561122 10061 21100 58005",
|
||||
"KGTF 1756Z 35010KT 1/2SM -SN FG VV09 M06/M08 A3051 RMK AOA "
|
||||
"933004 SFC VSBY 3/4 "
|
||||
"PCPN M SLP393 60010 T10611077 11044 21067 53013",
|
||||
"KHLN 1756Z 35012KT 10SM SCT032 OVC060 M02/M09 A3048 RMK AOA "
|
||||
"SLP369 60000 T10171094 11017 21061 53006",
|
||||
"KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 61104 "
|
||||
"71235 T01110045 10111 20000 401720056 58002",
|
||||
"METAR KLAX 04281156Z AUTO VRB100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC "
|
||||
"+TS BLPY FEW000 BKN050 SCT150 OVC250 3/M1 A2991 RMK "
|
||||
"TORNADO B13 DSNT NE A02 PK WND 18515/45 "
|
||||
"WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"VIS 2 1/2 RY11 OCNL LTG VCY STN "
|
||||
"RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RY11 "
|
||||
"PRESFR PRESRR SLP013 FG FEW000 VIS NW2 1/2 GR 3/4 "
|
||||
"VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC "
|
||||
"FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 "
|
||||
"933125 98096 P 0125 60225 70565 "
|
||||
"T00261015 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
|
||||
|
||||
"METAR KGFI 041356Z AUTO 17012KT 130V210 3 1/2SM R15L/0500FT -RA "
|
||||
"SCT050 OVC110 26/18 A2991 RMK FUNNEL CLOUDS A02 RAB30 "
|
||||
"SLP 101 GR M1/4 VIRGA SCT V BKN P 0010 T02640178",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 "
|
||||
"RMK WATERSPOUTS VCY STN NW A02 SLP 101 10288 20243 52021 $ ",
|
||||
|
||||
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"A2900 RMK A02A PK WND 18056/28 OCNL LTG AP "
|
||||
"RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 T01990182",
|
||||
|
||||
"KABE 281900Z NIL",
|
||||
|
||||
"METAR KPIT NIL",
|
||||
|
||||
"METAR KCLE 04281156Z 170100G135KT 110V180 M1/4SM "
|
||||
"R01L/P6000FT +TSSHRA VCFG "
|
||||
"BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"CIG 1000V1500 PRESFR FRQ LTG CG NW "
|
||||
"RAB1030E1145 FZDZE56 PRESRR SLP135 GS "
|
||||
"T1263 "
|
||||
"VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"METAR KPHL 040256Z AUTO 170100G135KT 130V210 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 LTG DSNT "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP037 GR 2 3/4 "
|
||||
"VIRGA E 8/365 4/178 P 0125 70565 21026 T0263 10369 60225 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"SPECI KGFI 041420Z AUTO 18030KT 2 1/2SM RVRNO TS -RA BKN008 "
|
||||
"OVC060 25/22 A2991 RMK A02 LTG DSNT W "
|
||||
"RAB15TSB20 PRESFR SLP101 P 0000 "
|
||||
"254/218",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR M1/4 "
|
||||
"VIRGA SE 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
|
||||
|
||||
|
||||
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
|
||||
"VIRGA 35 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 "
|
||||
"VIRGA 35 8/365 4/178 P 0125 21026 70565 10369 60225 T0263 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
|
||||
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 18515/45 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
|
||||
"VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 185150/1345 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
|
||||
"VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO",
|
||||
|
||||
|
||||
|
||||
"METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 RMK "
|
||||
"A02 SLP 101 10288 20243 52021",
|
||||
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 M199/M182",
|
||||
|
||||
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 M199/182",
|
||||
|
||||
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 199/M182",
|
||||
|
||||
"METAR APIT 171755Z AUTO 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 4/369 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 8/563 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 1/2V2 SLP875 SGB1213E1225",
|
||||
|
||||
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
|
||||
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK SLP056 "
|
||||
"RAE0123",
|
||||
|
||||
"SPECI APIT 171755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 8/321 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 SLP875 FGB1713",
|
||||
|
||||
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2 SLP875",
|
||||
|
||||
|
||||
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 1/2V2 1/2 SLP875",
|
||||
|
||||
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2 1/2 SLP875",
|
||||
|
||||
|
||||
"EGPF 1720Z 00000KT 9999 -SHRA STC014 SCT020CB BNK024 12/09 "
|
||||
"Q1003 NOSIG",
|
||||
|
||||
"NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG",
|
||||
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
|
||||
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT",
|
||||
"DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015",
|
||||
"DAAT 1830Z 30010KT CAVOK 29/06 Q1019",
|
||||
|
||||
"GQPP 1800Z 34023KT 3000 DRSA SKC 24/20 Q1011 NSG",
|
||||
"DAAG 1830Z 06006KT 9999 SCT020 25/22 Q1015",
|
||||
"DABB 1830Z 04010KT 9999 SCT030TCU SCT033CB 27/18 Q1017",
|
||||
"DABC 1830Z 00000KT 9999 SCT026TCU SCT036CB 22/18 Q1020 RETS",
|
||||
|
||||
"NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG",
|
||||
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
|
||||
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK K",
|
||||
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
|
||||
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT",
|
||||
"DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015",
|
||||
|
||||
"GFLL 1900Z NIL",
|
||||
|
||||
"GOOY 1800Z 03006G17KT 340V080 6000 TSRA BKN016 BKN030CB "
|
||||
"BKN133 26/23 Q1013 NOSIG",
|
||||
|
||||
"GCXO 1930Z 32018KT 8000 SCT003 SCT007 18/16 Q1019",
|
||||
|
||||
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 1/2V2",
|
||||
|
||||
"BPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2",
|
||||
|
||||
"CPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2 1/2",
|
||||
|
||||
"DPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 1/2V2 1/2",
|
||||
|
||||
|
||||
"FPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 3/4V2 1/2",
|
||||
|
||||
"GPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 3/4V3",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/M16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/M16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/M16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/MM A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/MM A2992",
|
||||
|
||||
NULL};
|
||||
|
||||
/***************************/
|
||||
/* DECLARE LOCAL VARIABLES */
|
||||
/***************************/
|
||||
|
||||
Decoded_METAR Metar;
|
||||
Decoded_METAR *Mptr = &Metar;
|
||||
int j,
|
||||
ErReturn;
|
||||
|
||||
|
||||
/***************************************************/
|
||||
/* START BODY OF MAIN ROUTINE FOR CALLING DcdMETAR */
|
||||
/***************************************************/
|
||||
|
||||
j = 0;
|
||||
|
||||
while( string[j] != NULL)
|
||||
{
|
||||
/*-- PRINT INPUT METAR REPORT ----------------------------*/
|
||||
printf("INPUT METAR REPORT: %s\n",string[j] );
|
||||
|
||||
/*-- DECODE INPUT REPORT ---------------------------------*/
|
||||
if ( (ErReturn = DcdMETAR( string[ j ], Mptr )) != 0 )
|
||||
printf("DcdMETAR: Error Return Number: %d\n",ErReturn);
|
||||
|
||||
/*-- PRINT DECODED METAR REPORT ELEMENTS -----------------*/
|
||||
prtDMETR( Mptr );
|
||||
|
||||
j++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#include "Local.h" /* standard header file */
|
||||
#include "Metar.h"
|
||||
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* Title: fracPart */
|
||||
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
|
||||
/* Date: 13 Jun 1995 */
|
||||
/* Programmer: CARL MCCALLA */
|
||||
/* Language: C/370 */
|
||||
/* */
|
||||
/* Abstract: Convert a character string fraction into a */
|
||||
/* decimal (floating point) number. */
|
||||
/* */
|
||||
/* External Functions Called: */
|
||||
/* None. */
|
||||
/* */
|
||||
/* Input: string - a pointer to a character string frac- */
|
||||
/* tion. */
|
||||
/* Output: A decimal (floating point) number. */
|
||||
/* */
|
||||
/* Modification History: */
|
||||
/* None. */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
|
||||
float fracPart( char *string )
|
||||
{
|
||||
|
||||
/***************************/
|
||||
/* DECLARE LOCAL VARIABLES */
|
||||
/***************************/
|
||||
|
||||
char buf[ 6 ],
|
||||
*slash;
|
||||
|
||||
float numerator,
|
||||
denominator;
|
||||
|
||||
/*************************/
|
||||
/* START BODY OF ROUTINE */
|
||||
/*************************/
|
||||
|
||||
slash = strchr(string, '/');
|
||||
|
||||
memset(buf , '\0', 6);
|
||||
strncpy( buf, string, slash-string);
|
||||
|
||||
numerator = (float) atoi(buf);
|
||||
|
||||
memset(buf , '\0', 6);
|
||||
strcpy( buf, slash+1);
|
||||
|
||||
denominator = (float) atoi(buf);
|
||||
|
||||
return (numerator/denominator);
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
includedir = @includedir@/metar
|
||||
|
||||
lib_LIBRARIES = libsgmetar.a
|
||||
|
||||
include_HEADERS = MetarReport.h MetarStation.h
|
||||
|
||||
libsgmetar_a_SOURCES = \
|
||||
Antoi.cpp Charcmp.cpp Dcdmetar.cpp Dcdmtrmk.cpp Drvmetar.c \
|
||||
Fracpart.cpp Local.h Metar.h \
|
||||
MetarReport.cpp \
|
||||
MetarStation.cpp \
|
||||
Prtdmetr.cpp Stspack2.cpp Stspack3.cpp
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
@@ -1,149 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="Metar" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=Metar - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Metar.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Metar.mak" CFG="Metar - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Metar - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "Metar - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Metar - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /W3 /GX /Zi /O2 /I "..\..\..\lib" /I "..\lib" /I "..\..\lib" /I "..\..\..\..\lib" /I ".." /I "..\.." /I "..\..\.." /I "..\..\..\.." /I "..\include" /I "..\..\include" /I "..\..\..\include" /I "..\..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "Metar - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /G6 /W3 /Gm /GX /Zi /Od /I "..\..\..\lib" /I "..\lib" /I "..\..\lib" /I "..\..\..\..\lib" /I ".." /I "..\.." /I "..\..\.." /I "..\..\..\.." /I "..\include" /I "..\..\include" /I "..\..\..\include" /I "..\..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Metar - Win32 Release"
|
||||
# Name "Metar - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Antoi.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Charcmp.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Dcdmetar.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Dcdmtrmk.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Fracpart.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MetarReport.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MetarStation.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Prtdmetr.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Stspack2.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Stspack3.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LOCAL.H
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\METAR.H
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MetarReport.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MetarStation.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,265 +0,0 @@
|
||||
#ifndef METARX
|
||||
#define METARX
|
||||
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* Title: METAR H */
|
||||
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
|
||||
/* Date: 19 Jan 1996 */
|
||||
/* Programmer: CARL MCCALLA */
|
||||
/* Language: C/370 */
|
||||
/* */
|
||||
/* Abstract: METAR Decoder Header File. */
|
||||
/* */
|
||||
/* Modification History: */
|
||||
/* None. */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
#include "Local.h" /* standard header file */
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* */
|
||||
/* RUNWAY VISUAL RANGE STRUCTURE DECLARATION */
|
||||
/* AND VARIABLE TYPE DEFINITION */
|
||||
/* */
|
||||
/*********************************************/
|
||||
|
||||
typedef struct runway_VisRange {
|
||||
char runway_designator[6];
|
||||
bool vrbl_visRange;
|
||||
bool below_min_RVR;
|
||||
bool above_max_RVR;
|
||||
int visRange;
|
||||
int Max_visRange;
|
||||
int Min_visRange;
|
||||
} Runway_VisRange;
|
||||
|
||||
/***********************************************/
|
||||
/* */
|
||||
/* DISPATCH VISUAL RANGE STRUCTURE DECLARATION */
|
||||
/* AND VARIABLE TYPE DEFINITION */
|
||||
/* */
|
||||
/***********************************************/
|
||||
|
||||
typedef struct dispatch_VisRange {
|
||||
bool vrbl_visRange;
|
||||
bool below_min_DVR;
|
||||
bool above_max_DVR;
|
||||
int visRange;
|
||||
int Max_visRange;
|
||||
int Min_visRange;
|
||||
} Dispatch_VisRange;
|
||||
|
||||
/*****************************************/
|
||||
/* */
|
||||
/* CLOUD CONDITION STRUCTURE DECLARATION */
|
||||
/* AND VARIABLE TYPE DEFINITION */
|
||||
/* */
|
||||
/*****************************************/
|
||||
|
||||
typedef struct cloud_Conditions {
|
||||
char cloud_type[5];
|
||||
char cloud_hgt_char[4];
|
||||
char other_cld_phenom[4];
|
||||
int cloud_hgt_meters;
|
||||
} Cloud_Conditions;
|
||||
|
||||
/*****************************************/
|
||||
/* */
|
||||
/* WIND GROUP DATA STRUCTURE DECLARATION */
|
||||
/* AND VARIABLE TYPE DEFINITION */
|
||||
/* */
|
||||
/*****************************************/
|
||||
|
||||
typedef struct windstruct {
|
||||
char windUnits[ 4 ];
|
||||
bool windVRB;
|
||||
int windDir;
|
||||
int windSpeed;
|
||||
int windGust;
|
||||
} WindStruct;
|
||||
|
||||
/*****************************************/
|
||||
/* */
|
||||
/* RECENT WX GROUP STRUCTURE DECLARATION */
|
||||
/* AND VARIABLE TYPE DEFINITION */
|
||||
/* */
|
||||
/*****************************************/
|
||||
|
||||
typedef struct recent_wx {
|
||||
char Recent_weather[ 5 ];
|
||||
int Bhh;
|
||||
int Bmm;
|
||||
int Ehh;
|
||||
int Emm;
|
||||
} Recent_Wx;
|
||||
|
||||
/***************************************/
|
||||
/* */
|
||||
/* DECODED METAR STRUCTURE DECLARATION */
|
||||
/* AND VARIABLE TYPE DEFINITION */
|
||||
/* */
|
||||
/***************************************/
|
||||
|
||||
typedef struct decoded_METAR {
|
||||
char synoptic_cloud_type[ 6 ];
|
||||
char snow_depth_group[ 6 ];
|
||||
char codeName[ 6 ];
|
||||
char stnid[5];
|
||||
char horiz_vsby[5];
|
||||
char dir_min_horiz_vsby[3];
|
||||
char vsby_Dir[ 3 ];
|
||||
char WxObstruct[10][8];
|
||||
char autoIndicator[5];
|
||||
char VSBY_2ndSite_LOC[10];
|
||||
char SKY_2ndSite_LOC[10];
|
||||
char SKY_2ndSite[10];
|
||||
char SectorVsby_Dir[ 3 ];
|
||||
char ObscurAloft[ 12 ];
|
||||
char ObscurAloftSkyCond[ 12 ];
|
||||
char VrbSkyBelow[ 4 ];
|
||||
char VrbSkyAbove[ 4 ];
|
||||
char LTG_DIR[ 3 ];
|
||||
char CloudLow;
|
||||
char CloudMedium;
|
||||
char CloudHigh;
|
||||
char CIG_2ndSite_LOC[10];
|
||||
char VIRGA_DIR[3];
|
||||
char TornadicType[15];
|
||||
char TornadicLOC[10];
|
||||
char TornadicDIR[4];
|
||||
char TornadicMovDir[3];
|
||||
char CHINO_LOC[6];
|
||||
char VISNO_LOC[6];
|
||||
char PartialObscurationAmt[2][7];
|
||||
char PartialObscurationPhenom[2][12];
|
||||
char SfcObscuration[6][10];
|
||||
char charPrevailVsby[12];
|
||||
char charVertVsby[10];
|
||||
char TS_LOC[3];
|
||||
char TS_MOVMNT[3];
|
||||
|
||||
bool Indeterminant3_6HrPrecip;
|
||||
bool CIGNO;
|
||||
bool SLPNO;
|
||||
bool ACFTMSHP;
|
||||
bool NOSPECI;
|
||||
bool FIRST;
|
||||
bool LAST;
|
||||
bool SunSensorOut;
|
||||
bool AUTO;
|
||||
bool COR;
|
||||
bool NIL_rpt;
|
||||
bool CAVOK;
|
||||
bool RVRNO;
|
||||
bool A_altstng;
|
||||
bool Q_altstng;
|
||||
bool VIRGA;
|
||||
bool VOLCASH;
|
||||
bool GR;
|
||||
bool CHINO;
|
||||
bool VISNO;
|
||||
bool PNO;
|
||||
bool PWINO;
|
||||
bool FZRANO;
|
||||
bool TSNO;
|
||||
bool DollarSign;
|
||||
bool PRESRR;
|
||||
bool PRESFR;
|
||||
bool Wshft_FROPA;
|
||||
bool OCNL_LTG;
|
||||
bool FRQ_LTG;
|
||||
bool CNS_LTG;
|
||||
bool CG_LTG;
|
||||
bool IC_LTG;
|
||||
bool CC_LTG;
|
||||
bool CA_LTG;
|
||||
bool DSNT_LTG;
|
||||
bool AP_LTG;
|
||||
bool VcyStn_LTG;
|
||||
bool OVHD_LTG;
|
||||
bool LightningVCTS;
|
||||
bool LightningTS;
|
||||
|
||||
int TornadicDistance;
|
||||
int ob_hour;
|
||||
int ob_minute;
|
||||
int ob_date;
|
||||
int minWnDir;
|
||||
int maxWnDir;
|
||||
int VertVsby;
|
||||
int temp;
|
||||
int dew_pt_temp;
|
||||
int QFE;
|
||||
int hectoPasc_altstng;
|
||||
int char_prestndcy;
|
||||
int minCeiling;
|
||||
int maxCeiling;
|
||||
int WshfTime_hour;
|
||||
int WshfTime_minute;
|
||||
int min_vrbl_wind_dir;
|
||||
int max_vrbl_wind_dir;
|
||||
int PKWND_dir;
|
||||
int PKWND_speed;
|
||||
int PKWND_hour;
|
||||
int PKWND_minute;
|
||||
int SKY_2ndSite_Meters;
|
||||
int Ceiling;
|
||||
int Estimated_Ceiling;
|
||||
int SNINCR;
|
||||
int SNINCR_TotalDepth;
|
||||
int SunshineDur;
|
||||
int ObscurAloftHgt;
|
||||
int VrbSkyLayerHgt;
|
||||
int Num8thsSkyObscured;
|
||||
int CIG_2ndSite_Meters;
|
||||
int snow_depth;
|
||||
int BTornadicHour;
|
||||
int BTornadicMinute;
|
||||
int ETornadicHour;
|
||||
int ETornadicMinute;
|
||||
|
||||
|
||||
float SectorVsby;
|
||||
float WaterEquivSnow;
|
||||
float VSBY_2ndSite;
|
||||
float prevail_vsbySM;
|
||||
float prevail_vsbyM;
|
||||
float prevail_vsbyKM;
|
||||
float prestndcy;
|
||||
float precip_amt;
|
||||
float precip_24_amt;
|
||||
float maxtemp;
|
||||
float mintemp;
|
||||
float max24temp;
|
||||
float min24temp;
|
||||
float minVsby;
|
||||
float maxVsby;
|
||||
float hourlyPrecip;
|
||||
float TWR_VSBY;
|
||||
float SFC_VSBY;
|
||||
float Temp_2_tenths;
|
||||
float DP_Temp_2_tenths;
|
||||
float SLP;
|
||||
float GR_Size;
|
||||
|
||||
double inches_altstng;
|
||||
|
||||
Runway_VisRange RRVR[12];
|
||||
Dispatch_VisRange DVR;
|
||||
Recent_Wx ReWx[3];
|
||||
WindStruct winData;
|
||||
Cloud_Conditions cldTypHgt[6];
|
||||
|
||||
} Decoded_METAR;
|
||||
|
||||
#define MAXWXSYMBOLS 10 /*-- NOT TO EXCEED 10 PRES. WX GRPS --*/
|
||||
#define MAXTOKENS 500 /*-- RPT NOT TO EXCEED 500 GRPS --*/
|
||||
|
||||
void prtDMETR( Decoded_METAR *Mptr );
|
||||
int DcdMETAR( char *string, Decoded_METAR *Mptr );
|
||||
|
||||
#endif
|
||||
@@ -1,309 +0,0 @@
|
||||
// Metar report implementation class code
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include STL_IOSTREAM
|
||||
|
||||
#include "MetarReport.h"
|
||||
#include "Metar.h"
|
||||
|
||||
SG_USING_STD(endl);
|
||||
SG_USING_STD(ostream);
|
||||
|
||||
CMetarReport::CMetarReport(
|
||||
char *s ) :
|
||||
m_DecodedReport( 0 )
|
||||
{
|
||||
m_DecodedReport = new Decoded_METAR;
|
||||
DcdMETAR( s, (Decoded_METAR *)m_DecodedReport );
|
||||
}
|
||||
|
||||
|
||||
CMetarReport::~CMetarReport()
|
||||
{
|
||||
}
|
||||
|
||||
static int DecodeDirChars( char* c )
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if ( c[0] )
|
||||
{
|
||||
if ( c[0] == 'E' ) r = 90;
|
||||
else if ( c[0] == 'S' ) r = 180;
|
||||
else if ( c[0] == 'W' ) r = 270;
|
||||
|
||||
if ( r == 0 )
|
||||
{
|
||||
if ( c[1] == 'E' ) r = 45;
|
||||
else if ( c[1] == 'W' ) r = 315;
|
||||
}
|
||||
else if ( r == 180 )
|
||||
{
|
||||
if ( c[1] == 'E' ) r = 135;
|
||||
else if ( c[1] == 'W' ) r = 225;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
char *CMetarReport::StationID()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->stnid;
|
||||
}
|
||||
|
||||
int CMetarReport::Day()
|
||||
{
|
||||
return ((Decoded_METAR*)m_DecodedReport)->ob_date;
|
||||
}
|
||||
|
||||
int CMetarReport::Hour()
|
||||
{
|
||||
return ((Decoded_METAR*)m_DecodedReport)->ob_hour;
|
||||
}
|
||||
|
||||
int CMetarReport::Minutes()
|
||||
{
|
||||
return ((Decoded_METAR*)m_DecodedReport)->ob_minute;
|
||||
}
|
||||
|
||||
int CMetarReport::WindDirection()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->winData.windDir;
|
||||
}
|
||||
|
||||
int CMetarReport::WindSpeed()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->winData.windSpeed;
|
||||
}
|
||||
|
||||
int CMetarReport::WindGustSpeed()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->winData.windGust;
|
||||
}
|
||||
|
||||
int CMetarReport::LightningDirection()
|
||||
{
|
||||
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->LTG_DIR );
|
||||
}
|
||||
|
||||
char CMetarReport::CloudLow()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->CloudLow;
|
||||
}
|
||||
|
||||
char CMetarReport::CloudMedium()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->CloudMedium;
|
||||
}
|
||||
|
||||
char CMetarReport::CloudHigh()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->CloudHigh;
|
||||
}
|
||||
|
||||
int CMetarReport::VirgaDirection()
|
||||
{
|
||||
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->VIRGA_DIR );
|
||||
}
|
||||
|
||||
int CMetarReport::TornadicDirection()
|
||||
{
|
||||
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->TornadicDIR );
|
||||
}
|
||||
|
||||
int CMetarReport::TornadicMovementDirection()
|
||||
{
|
||||
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->TornadicMovDir );
|
||||
}
|
||||
|
||||
int CMetarReport::ThunderStormDirection()
|
||||
{
|
||||
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->TS_LOC );
|
||||
}
|
||||
|
||||
int CMetarReport::ThunderStormMovementDirection()
|
||||
{
|
||||
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->TS_MOVMNT );
|
||||
}
|
||||
|
||||
bool CMetarReport::Virga()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->VIRGA;
|
||||
}
|
||||
|
||||
bool CMetarReport::VolcanicAsh()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->VOLCASH;
|
||||
}
|
||||
|
||||
bool CMetarReport::Hail()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->GR;
|
||||
}
|
||||
|
||||
bool CMetarReport::OccationalLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->OCNL_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::FrequentLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->FRQ_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::ContinuousLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->CNS_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::CloudToGroundLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->CG_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::InterCloudLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->IC_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::CloudToCloudLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->CC_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::CloudToAirLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->CA_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::DistantLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->DSNT_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::AirportLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->AP_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::VicinityLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->VcyStn_LTG;
|
||||
}
|
||||
|
||||
bool CMetarReport::OverheadLightning()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->OVHD_LTG;
|
||||
}
|
||||
|
||||
int CMetarReport::Temperature()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->temp;
|
||||
}
|
||||
|
||||
int CMetarReport::DewpointTemperature()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->dew_pt_temp;
|
||||
}
|
||||
|
||||
int CMetarReport::VerticalVisibility() // Meters
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->VertVsby;
|
||||
}
|
||||
|
||||
int CMetarReport::Ceiling()
|
||||
{
|
||||
return
|
||||
(int)(SG_FEET_TO_METER*((Decoded_METAR *)m_DecodedReport)->Ceiling);
|
||||
}
|
||||
|
||||
int CMetarReport::EstimatedCeiling()
|
||||
{
|
||||
return
|
||||
(int)(SG_FEET_TO_METER
|
||||
* ((Decoded_METAR *)m_DecodedReport)->Estimated_Ceiling);
|
||||
}
|
||||
|
||||
int CMetarReport::VariableSkyLayerHeight()
|
||||
{
|
||||
return
|
||||
(int)(SG_FEET_TO_METER
|
||||
* ((Decoded_METAR *)m_DecodedReport)->VrbSkyLayerHgt);
|
||||
}
|
||||
|
||||
int CMetarReport::SnowDepthInches()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->snow_depth;
|
||||
}
|
||||
|
||||
|
||||
ostream&
|
||||
operator << ( ostream& out, CMetarReport& p )
|
||||
{
|
||||
return out
|
||||
<< "StationID " << p.StationID()
|
||||
<< " WindDirection " << p.WindDirection()
|
||||
<< " WindSpeed " << p.WindSpeed()
|
||||
<< " WindGustSpeed " << p.WindGustSpeed() << endl
|
||||
<< "CloudLow " << p.CloudLow()
|
||||
<< " CloudMedium " << p.CloudMedium()
|
||||
<< " CloudHigh " << p.CloudHigh() << endl
|
||||
<< "TornadicDirection " << p.TornadicDirection()
|
||||
<< " TornadicMovementDirection " << p.TornadicMovementDirection() << endl
|
||||
<< "ThunderStormDirection " << p.ThunderStormDirection()
|
||||
<< " ThunderStormMovementDirection " << p.ThunderStormMovementDirection() << endl
|
||||
<< "Virga " << p.Virga()
|
||||
<< " VirgaDirection " << p.VirgaDirection() << endl
|
||||
<< "VolcanicAsh " << p.VolcanicAsh() << endl
|
||||
<< "Hail " << p.Hail() << endl
|
||||
<< "LightningDirection " << p.LightningDirection()
|
||||
<< " OccationalLightning " << p.OccationalLightning()
|
||||
<< " FrequentLightning " << p.FrequentLightning()
|
||||
<< " ContinuousLightning " << p.ContinuousLightning() << endl
|
||||
<< "CloudToGroundLightning " << p.CloudToGroundLightning()
|
||||
<< " InterCloudLightning " << p.InterCloudLightning()
|
||||
<< " CloudToCloudLightning " << p.CloudToCloudLightning()
|
||||
<< " CloudToAirLightning " << p.CloudToAirLightning() << endl
|
||||
<< "DistantLightning " << p.DistantLightning()
|
||||
<< " AirportLightning " << p.AirportLightning()
|
||||
<< " VicinityLightning " << p.VicinityLightning()
|
||||
<< " OverheadLightning " << p.OverheadLightning() << endl
|
||||
<< "VerticalVisibility " << p.VerticalVisibility() << endl // Meters
|
||||
<< "Temperature " << p.Temperature()
|
||||
<< " DewpointTemperature " << p.DewpointTemperature() << endl
|
||||
<< "Ceiling " << p.Ceiling()
|
||||
<< " EstimatedCeiling " << p.EstimatedCeiling()
|
||||
<< " VariableSkyLayerHeight " << p.VariableSkyLayerHeight() << endl
|
||||
<< "SnowDepthInches " << p.SnowDepthInches() << endl
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
double CMetarReport::AirPressure()
|
||||
{
|
||||
return ((Decoded_METAR *)m_DecodedReport)->inches_altstng;
|
||||
}
|
||||
|
||||
void CMetarReport::dump()
|
||||
{
|
||||
prtDMETR( (Decoded_METAR *)m_DecodedReport );
|
||||
}
|
||||
|
||||
double CMetarReport::PrevailVisibility()
|
||||
{
|
||||
//Values from each visibility field converted to meters.
|
||||
double smiles;
|
||||
double km;
|
||||
double meters;
|
||||
smiles = ((Decoded_METAR*) m_DecodedReport)->prevail_vsbySM * 1609.34;
|
||||
km = ((Decoded_METAR*) m_DecodedReport)->prevail_vsbyKM * 1000;
|
||||
meters = ((Decoded_METAR*) m_DecodedReport)->prevail_vsbyM;
|
||||
|
||||
/* Return the smallest one. If the field is specified it should have been
|
||||
set to MAX_INT */
|
||||
if(smiles < km && smiles < meters)
|
||||
return smiles;
|
||||
else
|
||||
return km < meters ? km : meters;
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
// Class encapulating the metar report information
|
||||
//
|
||||
// Individual METAR reports are found in this directory:
|
||||
// ftp://weather.noaa.gov/data/observations/metar/stations
|
||||
//
|
||||
|
||||
#ifndef _MetarReport_
|
||||
#define _MetarReport_
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include STL_IOSTREAM
|
||||
#include STL_STRING
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
|
||||
SG_USING_STD(string);
|
||||
|
||||
class CMetarReport
|
||||
{
|
||||
// Typedefs, enumerations
|
||||
|
||||
// Attributes
|
||||
private:
|
||||
void *m_DecodedReport;
|
||||
// A void pointer which is cast to the correct type in the cpp file.
|
||||
// I don't want the ugly metar structure and header files dragged into
|
||||
// every report user program file.
|
||||
// Probably should be a smart pointer if copy constructor and assignment
|
||||
// is allowed.
|
||||
|
||||
// Operations
|
||||
|
||||
public:
|
||||
CMetarReport(
|
||||
char *s );
|
||||
// Constructor
|
||||
|
||||
~CMetarReport();
|
||||
// Destructor
|
||||
|
||||
char *StationID();
|
||||
|
||||
int Day(); // The day of month on which the report was issued.
|
||||
int Hour(); // The hour of the day the report was issued.
|
||||
int Minutes(); //Minutes past the hour of the report issue time.
|
||||
|
||||
// Directions in degrees
|
||||
// Speed in knots
|
||||
// Altitude in meters
|
||||
// Temperature in centigrade
|
||||
|
||||
int WindDirection();
|
||||
int WindSpeed();
|
||||
int WindGustSpeed();
|
||||
|
||||
// Add cloud more cloud info...
|
||||
// Cloud code characters...
|
||||
char CloudLow();
|
||||
char CloudMedium();
|
||||
char CloudHigh();
|
||||
|
||||
bool Virga();
|
||||
int VirgaDirection();
|
||||
|
||||
int TornadicDirection();
|
||||
int TornadicMovementDirection();
|
||||
|
||||
int ThunderStormDirection();
|
||||
int ThunderStormMovementDirection();
|
||||
|
||||
bool VolcanicAsh();
|
||||
bool Hail();
|
||||
|
||||
int LightningDirection();
|
||||
bool OccationalLightning();
|
||||
bool FrequentLightning();
|
||||
bool ContinuousLightning();
|
||||
bool Lightning()
|
||||
{
|
||||
return OccationalLightning() || FrequentLightning() || ContinuousLightning();
|
||||
}
|
||||
|
||||
bool CloudToGroundLightning();
|
||||
bool InterCloudLightning();
|
||||
bool CloudToCloudLightning();
|
||||
bool CloudToAirLightning();
|
||||
|
||||
bool DistantLightning();
|
||||
bool AirportLightning();
|
||||
bool OverheadLightning();
|
||||
bool VicinityLightning();
|
||||
|
||||
int Temperature();
|
||||
int DewpointTemperature();
|
||||
|
||||
int VerticalVisibility();
|
||||
int Ceiling();
|
||||
int EstimatedCeiling();
|
||||
int VariableSkyLayerHeight();
|
||||
|
||||
int SnowDepthInches();
|
||||
|
||||
double AirPressure(); //Return the air pressure in InchesHg.
|
||||
double PrevailVisibility(); // Prevailing Visibility in meters.
|
||||
void dump();
|
||||
|
||||
private:
|
||||
CMetarReport(
|
||||
const CMetarReport &rNewObj );
|
||||
// Copy constructor. Not implemented.
|
||||
|
||||
CMetarReport &operator =(
|
||||
const CMetarReport &rObj );
|
||||
// Assignment operator. Not implemented.
|
||||
};
|
||||
|
||||
ostream& operator << ( ostream&, CMetarReport& );
|
||||
|
||||
#endif
|
||||
@@ -1,216 +0,0 @@
|
||||
// Metar station implementation code
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include STL_IOSTREAM
|
||||
#include <stdio.h>
|
||||
|
||||
#include "MetarStation.h"
|
||||
#include <algorithm>
|
||||
|
||||
SG_USING_STD(ostream);
|
||||
SG_USING_STD(cout);
|
||||
SG_USING_STD(endl);
|
||||
|
||||
|
||||
double CMetarStation::decodeDMS( char *b )
|
||||
{
|
||||
double r = 0;
|
||||
double m = 0;
|
||||
double s = 0;
|
||||
if ( *b )
|
||||
{
|
||||
// Degrees
|
||||
r = (*b - '0') * 10.0; b++;
|
||||
r += (*b - '0'); b++;
|
||||
if ( *b != '-' )
|
||||
{
|
||||
r *= 10;
|
||||
r += (*b - '0'); b++;
|
||||
}
|
||||
b++;
|
||||
// Minutes
|
||||
m = (*b - '0') * 10.0; b++;
|
||||
m += (*b - '0'); b++;
|
||||
r += m/60.0;
|
||||
if ( *b == '-' )
|
||||
{
|
||||
// Seconds
|
||||
b++;
|
||||
s = (*b - '0') * 10.0; b++;
|
||||
s += (*b - '0'); b++;
|
||||
}
|
||||
r += s/3600.0;
|
||||
// Direction (E W N S)
|
||||
if ( *b == 'W' || *b == 'S' ) r = -r;
|
||||
}
|
||||
return r * SGD_DEGREES_TO_RADIANS;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
// Decodes METAR station string of this format:
|
||||
// KPUB;72;464;Pueblo, Pueblo Memorial Airport;CO;United States;4;38-17-24N;104-29-54W;38-17-03N;104-29-43W;1440;1420;P
|
||||
|
||||
CMetarStation::CMetarStation(
|
||||
char *s )
|
||||
{
|
||||
char *t;
|
||||
t = strchr( s, ';' ); *t = 0; t++;
|
||||
m_ID = s;
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
m_number = atoi( s ) * 1000;
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
m_number += atoi( s );
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
m_name = s;
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
m_state = s;
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
m_country = s;
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
m_region = atoi( s );
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
double latitude = decodeDMS( s );
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
double longitude = decodeDMS( s );
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
double ulatitude = decodeDMS( s );
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
double ulongitude = decodeDMS( s );
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
double altitude = atoi( s ) * SG_FEET_TO_METER;
|
||||
m_altitude = (int)altitude;
|
||||
s = t; t = strchr( s, ';' ); *t = 0; t++;
|
||||
double ualtitude = atoi( s ) * SG_FEET_TO_METER;
|
||||
Point3D p( longitude, latitude, altitude+SG_EQUATORIAL_RADIUS_M );
|
||||
m_locationPolar = p;
|
||||
m_locationCart = sgPolarToCart3d( p );
|
||||
Point3D up( ulongitude, ulatitude, ualtitude+SG_EQUATORIAL_RADIUS_M );
|
||||
m_upperLocationPolar = up;
|
||||
m_upperLocationCart = sgPolarToCart3d( up );
|
||||
s = t;
|
||||
m_pFlag = s[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMetarStation::dump()
|
||||
{
|
||||
cout << "ID:" << ID();
|
||||
cout << endl;
|
||||
cout << "number:" << number();
|
||||
cout << endl;
|
||||
cout << "name:" << name();
|
||||
cout << endl;
|
||||
cout << "state:" << state();
|
||||
cout << endl;
|
||||
cout << "country:" << country();
|
||||
cout << endl;
|
||||
cout << "region:" << region();
|
||||
cout << endl;
|
||||
cout << "Location (cart):" << locationCart();
|
||||
cout << endl;
|
||||
cout << "Location (polar):" << locationPolar();
|
||||
cout << endl;
|
||||
cout << "Upper Location (cart):" << upperLocationCart();
|
||||
cout << endl;
|
||||
cout << "Upper Location (polar):" << upperLocationPolar();
|
||||
cout << endl;
|
||||
cout << "P flag:" << pFlag();
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CMetarStationDB::CMetarStationDB(const char * dbPath)
|
||||
{
|
||||
// Read the list of metar stations, decoding and adding to global list.
|
||||
|
||||
CMetarStation *m;
|
||||
char buf[256];
|
||||
|
||||
|
||||
// Open the metar station list
|
||||
FILE *f = fopen( dbPath, "r" );
|
||||
|
||||
|
||||
if ( f != NULL ) {
|
||||
// Read each line, create an instance of a station, and add it to the vector
|
||||
while ( fgets( buf, 256, f) != NULL && feof( f ) == 0 ) {
|
||||
// cout << buf << endl;
|
||||
m = new CMetarStation( buf );
|
||||
//m->dump();
|
||||
METAR_Stations[m->ID()]=( m );
|
||||
}
|
||||
|
||||
// Close the list
|
||||
fclose( f );
|
||||
// cout << METAR_Stations.size() << " Metar stations" << endl;
|
||||
|
||||
} else {
|
||||
// cout << "Could not open MetarStations file " << endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CMetarStation * CMetarStationDB::find( std::string stationID )
|
||||
{
|
||||
std::map<std::string,CMetarStation*>::iterator target;
|
||||
target = METAR_Stations.find(stationID);
|
||||
if(target!= METAR_Stations.end() )
|
||||
return target->second;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CMetarStation * CMetarStationDB::find( Point3D locationCart )
|
||||
{
|
||||
std::map<std::string,CMetarStation*>::iterator itr;
|
||||
double bestDist = 99999999;
|
||||
CMetarStation *bestStation = NULL;
|
||||
Point3D curLocation = locationCart;
|
||||
itr = METAR_Stations.begin();
|
||||
while(itr != METAR_Stations.end())
|
||||
{
|
||||
double dist = itr->second->locationCart().distance3Dsquared( curLocation );
|
||||
if (dist < bestDist )
|
||||
{
|
||||
bestDist = dist;
|
||||
bestStation = itr->second;
|
||||
}
|
||||
itr++;
|
||||
}
|
||||
|
||||
return bestStation;
|
||||
}
|
||||
|
||||
|
||||
CMetarStationDB::~CMetarStationDB() {
|
||||
std::map<std::string,CMetarStation*>::iterator itr;
|
||||
for(itr = METAR_Stations.begin(); itr != METAR_Stations.end(); itr++)
|
||||
{
|
||||
delete itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
ostream&
|
||||
operator << ( ostream& out, const CMetarStation& p )
|
||||
{
|
||||
return out
|
||||
<< "ID:" << p.m_ID << endl
|
||||
<< "number:" << p.m_number << endl
|
||||
<< "name:" << p.m_name << endl
|
||||
<< "state:" << p.m_state << endl
|
||||
<< "country:" << p.m_country << endl
|
||||
<< "region:" << p.m_region << endl
|
||||
<< "Location (cart):" << p.m_locationCart << endl
|
||||
<< "Location (polar):" << p.m_locationCart << endl
|
||||
<< "Upper Location (cart):" << p.m_upperLocationCart << endl
|
||||
<< "Upper Location (polar):" << p.m_upperLocationPolar << endl
|
||||
<< "P flag:" << p.m_pFlag << endl;
|
||||
}
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
// Class encapulating the metar station information
|
||||
//
|
||||
// METAR station information is kept in this file:
|
||||
// http://www.nws.noaa.gov/pub/stninfo/nsd_cccc.gz
|
||||
// http://www.nws.noaa.gov/pub/stninfo/nsd_cccc.txt
|
||||
|
||||
|
||||
#ifndef _MetarStation_
|
||||
#define _MetarStation_
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include STL_IOSTREAM
|
||||
#include STL_STRING
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
|
||||
SG_USING_STD(string);
|
||||
SG_USING_STD(vector);
|
||||
SG_USING_STD(map);
|
||||
|
||||
class CMetarStationDB;
|
||||
|
||||
class CMetarStation
|
||||
{
|
||||
// Attributes
|
||||
private:
|
||||
std::string m_ID;
|
||||
unsigned long m_number;
|
||||
std::string m_name;
|
||||
std::string m_state;
|
||||
std::string m_country;
|
||||
int m_region;
|
||||
Point3D m_locationPolar;
|
||||
Point3D m_upperLocationPolar;
|
||||
Point3D m_locationCart;
|
||||
Point3D m_upperLocationCart;
|
||||
int m_altitude;
|
||||
int m_upperAltitude;
|
||||
char m_pFlag;
|
||||
|
||||
// Operations
|
||||
private:
|
||||
double decodeDMS( char *b );
|
||||
|
||||
|
||||
|
||||
CMetarStation(
|
||||
char *s );
|
||||
// Constructor
|
||||
|
||||
~CMetarStation()
|
||||
{
|
||||
}
|
||||
// Destructor
|
||||
|
||||
public:
|
||||
std::string &ID() { return m_ID; }
|
||||
unsigned long number() { return m_number; }
|
||||
std::string &name() { return m_name; }
|
||||
std::string &state() { return m_state; }
|
||||
std::string &country() { return m_country; }
|
||||
int region() { return m_region; }
|
||||
unsigned int Altitude() { //Returns the stations height above MSL in M.
|
||||
return m_altitude;}
|
||||
Point3D &locationPolar() { return m_locationPolar; }
|
||||
Point3D &upperLocationPolar() { return m_upperLocationPolar; }
|
||||
Point3D &locationCart() { return m_locationCart; }
|
||||
Point3D &upperLocationCart() { return m_upperLocationCart; }
|
||||
char pFlag() { return m_pFlag; }
|
||||
// Get attributes
|
||||
|
||||
friend ostream& operator << ( ostream&, const CMetarStation& );
|
||||
void dump();
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
CMetarStation(
|
||||
const CMetarStation &rNewObj );
|
||||
// Copy constructor. Not implemented.
|
||||
|
||||
CMetarStation &operator =(
|
||||
const CMetarStation &rObj );
|
||||
// Assignment operator. Not implemented.
|
||||
|
||||
friend class CMetarStationDB;
|
||||
};
|
||||
|
||||
|
||||
class CMetarStationDB
|
||||
{
|
||||
|
||||
private:
|
||||
std::string databasePath; //The path of the database file.
|
||||
std::map<std::string , CMetarStation *> METAR_Stations;
|
||||
CMetarStation * bestStation;
|
||||
|
||||
public:
|
||||
CMetarStation *find( std::string stationID );
|
||||
CMetarStation * find( Point3D locationCart );
|
||||
CMetarStationDB(const char * dbFile);
|
||||
~CMetarStationDB();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,558 +0,0 @@
|
||||
// Metar Library test
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include GLUT_H
|
||||
|
||||
#include <iostream>
|
||||
#include "../MetarReport.h"
|
||||
#include "../MetarStation.h"
|
||||
|
||||
static char *report[] =
|
||||
{
|
||||
"KAST 221156Z COR 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
|
||||
|
||||
"KAST COR 221156Z 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
|
||||
|
||||
"KAST COR 221156Z 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
|
||||
|
||||
"KP88 COR 221156 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
|
||||
|
||||
"KP88 COR 221156 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 6//// 70109 T00890084 10100 20089 55005",
|
||||
|
||||
|
||||
"EPIT 1755 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1/2V3/4",
|
||||
|
||||
"KFAR 181154Z 10003KT 1/4SM HZ CLR 16/13 A2988 RMK AO2 "
|
||||
"SLP117 56012 10345 20226 T01610133 $",
|
||||
|
||||
"KFAR 181154Z 10003KT 1/SM HZ CLR 16/13 A2988 RMK AO2 "
|
||||
"SLP117 56012 10345 20226 T01610133 $",
|
||||
|
||||
"RKSS 21009KT 1400 RP2000 // ////// 21/20 1006/2972 NOSIG",
|
||||
|
||||
"RKSS 1200 21009KT 1400 RP2000 // ////// 21/20 1006/2972 NOSIG",
|
||||
|
||||
"RKSS 1130Z 23011KT 1100 R14R/P1500N R14L/P1500N BR SCT010 BKN030 "
|
||||
"BKN080 21/21 Q1006 NOSIG",
|
||||
|
||||
"RKSS 1130Z 23011KT 1100 R14R/P1500 R14L/P1500 BR SCT010 BKN030 "
|
||||
"BKN080 21/21 Q1006 NOSIG",
|
||||
|
||||
"KFAR 181154Z 10003KT 4SM HZ CLR 16/13 A2988 RMK AO2 "
|
||||
"SLP117 56012 1//// 2//// T01610133 $",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE DUE LO CLD SLP186",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE DUE10 LO CLD SLP186",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE DUE9 LO CLD SLP186",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE FZDZE10 LO CLD SLP186",
|
||||
|
||||
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
|
||||
"SF6SC1 VSBY RDCE FZDZE9 LO CLD SLP186",
|
||||
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 30/XX Q1015",
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 M30/XX Q1015",
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 MM/XX Q1015",
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 MM/30 Q1015",
|
||||
"MKJP 1400Z 13011KT 9999 FEW022 MM/M30 Q1015",
|
||||
|
||||
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 BKN045 OVC090 "
|
||||
"SCT120 FEW250 RMK OCNL LTGICCG OHD",
|
||||
|
||||
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 07/01 Q1011 "
|
||||
"RMK TEMPO 8000 -SHRA BKN015 FRQ LTG VC",
|
||||
|
||||
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 07/01 Q1011 "
|
||||
"RMK TEMPO 8000 -SHRA BKN015 LTG DSNT W",
|
||||
|
||||
"METAR KLAX 281156Z AUTO VRB100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC "
|
||||
"+TS BLPY FEW/// SCT000 BKN050 SCT150 OVC250 3/M1 A2991 RMK "
|
||||
"TORNADO B13E45 6 NE MOV E A02 PK WND 18515/45 "
|
||||
"WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"VIS 2 1/2 RY11 "
|
||||
"DVR/1000V1600FT "
|
||||
"OCNL LTG VCY STN "
|
||||
"RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RY11 "
|
||||
"PRESFR PRESRR SLP013 FG FEW/// HZ SCT000 VIS NW 2 1/2 GR 3/4 "
|
||||
"VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC "
|
||||
"FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 "
|
||||
"933125 98096 P 0125 60225 70565 "
|
||||
"T00261015 10369 21026 "
|
||||
"404800360 52101 VISNO RY05 CHINO RY27 PNO RVRNO "
|
||||
"PWINO FZRANO TSNO $",
|
||||
|
||||
"KBOS 251356Z 26011KT 10SM CLR 12/02 A2995 RMK AO2 SC VCNTY "
|
||||
"STN SSE-NNW SCT CI ABV SLP141 T01220023",
|
||||
|
||||
"EFHK 36009KT 340V060 CAVOK 12/M02 Q1013 NOSIG",
|
||||
"EGKK 24011KT 210V300 9999 SCT020 BKN045 12/06 Q1007 NOSIG",
|
||||
"EGPD 31018KT 8000 RA FEW013 BKN021 OVC045 06/04 Q0994 NOSIG",
|
||||
"EKCH 16012KT CAVOK 20/07 Q1006 NOSIG",
|
||||
"ESKN 10014KT 9000 BR SCT100 14/04 Q1010",
|
||||
"LOWW 231450Z 14017KT CAVOK 23/07 Q1010 NOSIG",
|
||||
|
||||
"METAR CYCH 171500Z CCA 30017KT 2SM -SN BKN006",
|
||||
|
||||
"METAR CYOW 171500Z CCA 30017KT 2SM -SN BKN006 OVC020 00/M02 "
|
||||
"A2957 RMK S35F4NS1 /S01/ SNW WET SNW MELTG ON GRND CIG 5-7 "
|
||||
"SLP018",
|
||||
|
||||
"KAST 221156Z AUTO 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005"
|
||||
" TSB0159E30 TS SE MOV NE",
|
||||
|
||||
"KAST 221156Z AUTO 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
|
||||
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005"
|
||||
" TSE0159 TS SE",
|
||||
|
||||
"KHVR 1756Z 31007KT 5SM -SN SCT011 BKN024 OVC030 M05/M08 A3056 "
|
||||
"RMK AOA 933004 "
|
||||
"BKN V SCT TNO PCPN 000 $ SLP389 4/015 60002 "
|
||||
"T10501077 11050 21078 51010",
|
||||
|
||||
"SPECI KGFI 041420Z AUTO 18030KT 3 1/2SM RVRNO TS -RA BKN008 OVC060 "
|
||||
"26/22 A2991 RMK A02 RA15TSB20 PRESFR SLP 101 P 0000 T02640218",
|
||||
|
||||
"METAR KCLE 281156Z 170100G135KT 110V180 M1/4SM "
|
||||
"R01L/P6000FT +TSSHRA VCFG "
|
||||
"BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"CIG 1000V1500 PRESFR FRQ LTG CG NW "
|
||||
"RAB1030E1145 FZDZE56 PRESRR SLP135 GS "
|
||||
"T1263 "
|
||||
"VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"CYQR 161700Z 15015KT 15SM SCT045 SCT090 BKN250 10/03 A2955 "
|
||||
"RMK SC1AC2C11 OB TAKEN H+ 5 DUE AWOS FAILURE SLP027",
|
||||
|
||||
"KPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2",
|
||||
|
||||
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 199/182",
|
||||
|
||||
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP701 P0254 199/182",
|
||||
|
||||
"KHLN 281156Z AUTO 27005KT 10SM OVC023 07/05 A3011 RMK AOA OVC V "
|
||||
"BKN $ SLP202 60000 70001 T00670050 10122 20061 53003",
|
||||
|
||||
"KPHX 281156Z 12004KT 10SM CLR 15/05 A2996 RMK AOA SLP135 T01500050 "
|
||||
"10250 20150 53006",
|
||||
"KFCA 281156Z 30003KT 10SM CLR 06/02 A3009 RMK AO TNO $ SLP191 "
|
||||
"T00610023 10167 20056 53003",
|
||||
"KAST 281156Z 00000KT 10SM BKN095 09/08 A2997 RMK AOA SLP150 "
|
||||
"T00940084 10161 20094 52005 ",
|
||||
"KHVR 281156Z 03003KT 10SM OVC020 09/07 A3010 RMK AO TNO ZRNO "
|
||||
"$ SLP194 T00940073 10156 20089 51005",
|
||||
"KGGW 281156Z 35006KT 5SM BR OVC010 10/09 A3003 RMK AOA $ SLP177 "
|
||||
"70003 T01000095 10156 20110 53008",
|
||||
"KELY 1153Z AUTO 14004KT 10SM SCT075 01/M01 A3011 RMK AOA TNO ZRNO "
|
||||
"SLP171 70001 T00061011 10139 21006 51005",
|
||||
"KFLG 281156Z 29006KT 10SM CLR 04/M01 A3012 RMK AO TNO SLP147 "
|
||||
"T00391011 21006 51004",
|
||||
"KGTF 281156Z 27005KT 7SM BKN080 04/04 A3010 RMK AOA SLP205 "
|
||||
"T00440045 10117 20039 51006",
|
||||
|
||||
"K13A 1918Z 20011KT 26/M06 RMK AO PKWND 020/RNO 644V264 T02611061",
|
||||
|
||||
"KP88 1919Z 09001KT 14/03 RMK AO / PKWND 002/RNO 158 Z T01440034",
|
||||
|
||||
"K40B 1924Z 29004KT 15/M07 RMK AO PKWND 011/RM MV263 T01501072",
|
||||
|
||||
"KGGW 1756Z 33018KT 10SM OVC015 M03/M06 A3041 RMK AOA SLP338 "
|
||||
"4/007 60002 T10281055 11028 21072 51009",
|
||||
"KPHX 1756Z 130004KT 10SM CLR 18/M03 A3001 RMK AOA SLP154 "
|
||||
"T01781033 10178 20067 58007",
|
||||
"KFCA 1756Z 29005KT 10SM CLR 05/M11 A3049 RMK AOA TNO SLP352 "
|
||||
"T00501111 10050 21044 50004",
|
||||
"KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 "
|
||||
"T01110045 10111 20000 50002",
|
||||
"KELY 1753Z 34010KT 10SM CLR 01/M07 A3022 RMK AOA TNO ZRNO "
|
||||
"SLP240 T00111066 10011 21078 58007",
|
||||
"KFLG 1756Z 07006KT 10SM CLR 06/M12 A3009 RMK AO TNO ZRNO "
|
||||
"SLP178 T00561122 10061 21100 58005",
|
||||
"KGTF 1756Z 35010KT 1/2SM -SN FG VV09 M06/M08 A3051 RMK AOA "
|
||||
"933004 SFC VSBY 3/4 "
|
||||
"PCPN M SLP393 60010 T10611077 11044 21067 53013",
|
||||
"KHLN 1756Z 35012KT 10SM SCT032 OVC060 M02/M09 A3048 RMK AOA "
|
||||
"SLP369 60000 T10171094 11017 21061 53006",
|
||||
"KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 61104 "
|
||||
"71235 T01110045 10111 20000 401720056 58002",
|
||||
"METAR KLAX 04281156Z AUTO VRB100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC "
|
||||
"+TS BLPY FEW000 BKN050 SCT150 OVC250 3/M1 A2991 RMK "
|
||||
"TORNADO B13 DSNT NE A02 PK WND 18515/45 "
|
||||
"WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"VIS 2 1/2 RY11 OCNL LTG VCY STN "
|
||||
"RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RY11 "
|
||||
"PRESFR PRESRR SLP013 FG FEW000 VIS NW2 1/2 GR 3/4 "
|
||||
"VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC "
|
||||
"FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 "
|
||||
"933125 98096 P 0125 60225 70565 "
|
||||
"T00261015 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 17012KT 130V210 3 1/2SM R15L/0500FT -RA "
|
||||
"SCT050 OVC110 26/18 A2991 RMK FUNNEL CLOUDS A02 RAB30 "
|
||||
"SLP 101 GR M1/4 VIRGA SCT V BKN P 0010 T02640178",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 "
|
||||
"RMK WATERSPOUTS VCY STN NW A02 SLP 101 10288 20243 52021 $ ",
|
||||
|
||||
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"A2900 RMK A02A PK WND 18056/28 OCNL LTG AP "
|
||||
"RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 T01990182",
|
||||
|
||||
"KABE 281900Z NIL",
|
||||
|
||||
"METAR KPIT NIL",
|
||||
|
||||
"METAR KCLE 04281156Z 170100G135KT 110V180 M1/4SM "
|
||||
"R01L/P6000FT +TSSHRA VCFG "
|
||||
"BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"CIG 1000V1500 PRESFR FRQ LTG CG NW "
|
||||
"RAB1030E1145 FZDZE56 PRESRR SLP135 GS "
|
||||
"T1263 "
|
||||
"VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"METAR KPHL 040256Z AUTO 170100G135KT 130V210 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 LTG DSNT "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP037 GR 2 3/4 "
|
||||
"VIRGA E 8/365 4/178 P 0125 70565 21026 T0263 10369 60225 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"SPECI KGFI 041420Z AUTO 18030KT 2 1/2SM RVRNO TS -RA BKN008 "
|
||||
"OVC060 25/22 A2991 RMK A02 LTG DSNT W "
|
||||
"RAB15TSB20 PRESFR SLP101 P 0000 "
|
||||
"254/218",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR M1/4 "
|
||||
"VIRGA SE 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
|
||||
"VIRGA 35 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 "
|
||||
"VIRGA 35 8/365 4/178 P 0125 21026 70565 10369 60225 T0263 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 18515/45 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
|
||||
"VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO $",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
|
||||
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
|
||||
"FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 185150/1345 "
|
||||
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
|
||||
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
|
||||
"VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 "
|
||||
"404800360 52101 PWINO FZRANO TSNO",
|
||||
|
||||
"METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 RMK "
|
||||
"A02 SLP 101 10288 20243 52021",
|
||||
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 M199/M182",
|
||||
|
||||
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 M199/182",
|
||||
|
||||
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
|
||||
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
|
||||
"SLP 701 P 0254 199/M182",
|
||||
|
||||
"METAR APIT 171755Z AUTO 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 4/369 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 8/563 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 1/2V2 SLP875 SGB1213E1225",
|
||||
|
||||
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
|
||||
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK SLP056 "
|
||||
"RAE0123",
|
||||
|
||||
"SPECI APIT 171755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 8/321 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 SLP875 FGB1713",
|
||||
|
||||
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2 SLP875",
|
||||
|
||||
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 1/2V2 1/2 SLP875",
|
||||
|
||||
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2 1/2 SLP875",
|
||||
|
||||
"EGPF 1720Z 00000KT 9999 -SHRA STC014 SCT020CB BNK024 12/09 "
|
||||
"Q1003 NOSIG",
|
||||
|
||||
"NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG",
|
||||
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
|
||||
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT",
|
||||
"DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015",
|
||||
"DAAT 1830Z 30010KT CAVOK 29/06 Q1019",
|
||||
|
||||
"GQPP 1800Z 34023KT 3000 DRSA SKC 24/20 Q1011 NSG",
|
||||
"DAAG 1830Z 06006KT 9999 SCT020 25/22 Q1015",
|
||||
"DABB 1830Z 04010KT 9999 SCT030TCU SCT033CB 27/18 Q1017",
|
||||
"DABC 1830Z 00000KT 9999 SCT026TCU SCT036CB 22/18 Q1020 RETS",
|
||||
|
||||
"NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG",
|
||||
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
|
||||
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK K",
|
||||
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
|
||||
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT",
|
||||
"DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015",
|
||||
|
||||
"GFLL 1900Z NIL",
|
||||
|
||||
"GOOY 1800Z 03006G17KT 340V080 6000 TSRA BKN016 BKN030CB "
|
||||
"BKN133 26/23 Q1013 NOSIG",
|
||||
|
||||
"GCXO 1930Z 32018KT 8000 SCT003 SCT007 18/16 Q1019",
|
||||
|
||||
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 1/2V2",
|
||||
|
||||
"BPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2",
|
||||
|
||||
"CPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1V2 1/2",
|
||||
|
||||
"DPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 1 1/2V2 1/2",
|
||||
|
||||
"FPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 3/4V2 1/2",
|
||||
|
||||
"GPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
|
||||
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
|
||||
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
|
||||
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
|
||||
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
|
||||
"SFC VIS 1 1/2 VIS 3/4V3",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/M16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/M16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/M16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/16 A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/MM A2992",
|
||||
|
||||
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
|
||||
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/MM A2992",
|
||||
|
||||
NULL};
|
||||
|
||||
|
||||
void dispMetarStation( CMetarStation *s )
|
||||
{
|
||||
glPointSize( 2.0 );
|
||||
glColor3d(1.0,1.0,0.0);
|
||||
glVertex3d( s->locationCart().x()/1000.0, s->locationCart().y()/1000.0, s->locationCart().z()/1000.0 );
|
||||
}
|
||||
|
||||
static int ii = 0;
|
||||
|
||||
void
|
||||
display(void)
|
||||
{
|
||||
glPushMatrix();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glRotatef((ii%360), 1.0, 0.0, 0.0);
|
||||
glRotatef((ii%360), 0.0, 1.0, 0.0);
|
||||
glRotatef((ii%360), 0.0, 0.0, 1.0);
|
||||
glBegin( GL_POINTS );
|
||||
CMetarStation::for_each( dispMetarStation );
|
||||
glEnd();
|
||||
glColor3d(0.0, 0.0, 1.0);
|
||||
glutWireSphere(SG_EARTH_RAD,32,16);
|
||||
glutSwapBuffers();
|
||||
ii++;
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
idle(void)
|
||||
{
|
||||
// std::cout << "Idle" << std::endl;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
init(void)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
gluPerspective( 50.0, 1.0, 1.0, 40000.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
gluLookAt(0.0, -19000.0, 0.0,
|
||||
0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
void testMetarStation(int argc,
|
||||
char **argv )
|
||||
{
|
||||
std::cout << "Display all Metar Stations" << std::endl;
|
||||
glutInit(&argc, argv);
|
||||
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
|
||||
glutCreateWindow("Metar Stations");
|
||||
glutDisplayFunc(display);
|
||||
glutIdleFunc(idle);
|
||||
init();
|
||||
glutMainLoop();
|
||||
}
|
||||
|
||||
void testMetarReport()
|
||||
{
|
||||
std::cout << "Decode some Metar reports" << std::endl;
|
||||
int i = 0;
|
||||
while ( report[i] )
|
||||
{
|
||||
std::cout << i << ": " << report[i] << std::endl;
|
||||
|
||||
CMetarReport dr( report[i] );
|
||||
|
||||
//dr.dump();
|
||||
std::cout << dr << std::endl;
|
||||
|
||||
CMetarStation *ms = CMetarStation::find( dr.StationID() );
|
||||
if ( ms )
|
||||
{
|
||||
std::cout << *ms << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "No corresponding METAR station found" << std::endl;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(
|
||||
int argc,
|
||||
char **argv )
|
||||
{
|
||||
std::cout << "Metar subsystem test" << std::endl;
|
||||
|
||||
testMetarReport();
|
||||
testMetarStation( argc, argv );
|
||||
return 0;
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="MetarLibTest" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=MetarLibTest - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "MetarLibTest.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "MetarLibTest.mak" CFG="MetarLibTest - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "MetarLibTest - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "MetarLibTest - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "MetarLibTest - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /Zi /O2 /I "..\..\..\lib" /I "..\lib" /I "..\..\lib" /I "..\..\..\..\lib" /I ".." /I "..\.." /I "..\..\.." /I "..\..\..\.." /I "..\include" /I "..\..\include" /I "..\..\..\include" /I "..\..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "MetarLibTest - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /GX /Zi /Od /I "..\..\..\lib" /I "..\lib" /I "..\..\lib" /I "..\..\..\..\lib" /I ".." /I "..\.." /I "..\..\.." /I "..\..\..\.." /I "..\include" /I "..\..\include" /I "..\..\..\include" /I "..\..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "MetarLibTest - Win32 Release"
|
||||
# Name "MetarLibTest - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MetarLibTest.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,95 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "LibMisc"=..\..\..\..\Win32\Workspace\LibMisc\LibMisc.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Metar"=..\Metar.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "MetarLibTest"=.\MetarLibTest.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Metar
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name MetarLib
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name glut
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name LibMisc
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "MetarTest"=.\MetarTest.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Metar
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name MetarLib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "glut"=..\..\..\..\..\glut\glut.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -1,587 +0,0 @@
|
||||
#include "Local.h" /* standard header file */
|
||||
#include "Metar.h"
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* Title: prtDMETR */
|
||||
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
|
||||
/* Date: 15 Sep 1994 */
|
||||
/* Programmer: CARL MCCALLA */
|
||||
/* Language: C/370 */
|
||||
/* */
|
||||
/* Abstract: prtDMETR prints, in order of the ASOS METAR */
|
||||
/* format, all non-initialized members of the structure */
|
||||
/* addressed by the Decoded_METAR pointer. */
|
||||
/* */
|
||||
/* External Functions Called: */
|
||||
/* None. */
|
||||
/* */
|
||||
/* Input: Mptr - ptr to a decoded_METAR structure. */
|
||||
/* */
|
||||
/* Output: NONE */
|
||||
/* */
|
||||
/* Modification History: */
|
||||
/* None. */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
void prtDMETR( Decoded_METAR *Mptr )
|
||||
{
|
||||
|
||||
/***************************/
|
||||
/* DECLARE LOCAL VARIABLES */
|
||||
/***************************/
|
||||
|
||||
int i;
|
||||
|
||||
/*************************/
|
||||
/* START BODY OF ROUTINE */
|
||||
/*************************/
|
||||
|
||||
printf("\n\n\n/*******************************************/\n");
|
||||
printf("/* THE DECODED METAR REPORT FOLLOWS */\n");
|
||||
printf("/*******************************************/\n\n");
|
||||
|
||||
if( Mptr->codeName[ 0 ] != '\0' )
|
||||
printf("REPORT CODE NAME : %s\n",Mptr->codeName);
|
||||
|
||||
if( Mptr->stnid[ 0 ] != '\0' )
|
||||
printf("STATION ID : %s\n",Mptr->stnid);
|
||||
|
||||
if( Mptr->ob_date != MAXINT )
|
||||
printf("OBSERVATION DAY : %d\n",Mptr->ob_date);
|
||||
|
||||
if( Mptr->ob_hour != MAXINT )
|
||||
printf("OBSERVATION HOUR : %d\n",Mptr->ob_hour);
|
||||
|
||||
if( Mptr->ob_minute != MAXINT )
|
||||
printf("OBSERVATION MINUTE : %d\n",Mptr->ob_minute);
|
||||
|
||||
if( Mptr->NIL_rpt )
|
||||
printf("NIL REPORT : TRUE\n");
|
||||
|
||||
if( Mptr->AUTO )
|
||||
printf("AUTO REPORT : TRUE\n");
|
||||
|
||||
if( Mptr->COR )
|
||||
printf("CORRECTED REPORT : TRUE\n");
|
||||
|
||||
if( Mptr->winData.windVRB )
|
||||
printf("WIND DIRECTION VRB : TRUE\n");
|
||||
|
||||
if( Mptr->winData.windDir != MAXINT )
|
||||
printf("WIND DIRECTION : %d\n",Mptr->winData.windDir);
|
||||
|
||||
if( Mptr->winData.windSpeed != MAXINT )
|
||||
printf("WIND SPEED : %d\n",Mptr->winData.windSpeed);
|
||||
|
||||
if( Mptr->winData.windGust != MAXINT )
|
||||
printf("WIND GUST : %d\n",Mptr->winData.windGust);
|
||||
|
||||
if( Mptr->winData.windUnits[ 0 ] != '\0' )
|
||||
printf("WIND UNITS : %s\n",Mptr->winData.windUnits);
|
||||
|
||||
if( Mptr->minWnDir != MAXINT )
|
||||
printf("MIN WIND DIRECTION : %d\n",Mptr->minWnDir);
|
||||
|
||||
if( Mptr->maxWnDir != MAXINT )
|
||||
printf("MAX WIND DIRECTION : %d\n",Mptr->maxWnDir);
|
||||
|
||||
if( Mptr->prevail_vsbyM != (float) MAXINT )
|
||||
printf("PREVAIL VSBY (M) : %f\n",Mptr->prevail_vsbyM);
|
||||
|
||||
if( Mptr->prevail_vsbyKM != (float) MAXINT )
|
||||
printf("PREVAIL VSBY (KM) : %f\n",Mptr->prevail_vsbyKM);
|
||||
|
||||
if( Mptr->prevail_vsbySM != (float) MAXINT )
|
||||
printf("PREVAIL VSBY (SM) : %.3f\n",Mptr->prevail_vsbySM);
|
||||
|
||||
if( Mptr->charPrevailVsby[0] != '\0' )
|
||||
printf("PREVAIL VSBY (CHAR) : %s\n",Mptr->charPrevailVsby);
|
||||
|
||||
if( Mptr->vsby_Dir[ 0 ] != '\0' )
|
||||
printf("VISIBILITY DIRECTION: %s\n",Mptr->vsby_Dir);
|
||||
|
||||
if( Mptr->RVRNO )
|
||||
printf("RVRNO : TRUE\n");
|
||||
|
||||
for ( i = 0; i < 12; i++ )
|
||||
{
|
||||
if( Mptr->RRVR[i].runway_designator[0] != '\0' )
|
||||
printf("RUNWAY DESIGNATOR : %s\n",
|
||||
Mptr->RRVR[i].runway_designator);
|
||||
|
||||
if( Mptr->RRVR[i].visRange != MAXINT )
|
||||
printf("R_WAY VIS RANGE (FT): %d\n",
|
||||
Mptr->RRVR[i].visRange);
|
||||
|
||||
if( Mptr->RRVR[i].vrbl_visRange )
|
||||
printf("VRBL VISUAL RANGE : TRUE\n");
|
||||
|
||||
if( Mptr->RRVR[i].below_min_RVR )
|
||||
printf("BELOW MIN RVR : TRUE\n");
|
||||
|
||||
if( Mptr->RRVR[i].above_max_RVR )
|
||||
printf("ABOVE MAX RVR : TRUE\n");
|
||||
|
||||
if( Mptr->RRVR[i].Max_visRange != MAXINT )
|
||||
printf("MX R_WAY VISRNG (FT): %d\n",
|
||||
Mptr->RRVR[i].Max_visRange);
|
||||
|
||||
if( Mptr->RRVR[i].Min_visRange != MAXINT )
|
||||
printf("MN R_WAY VISRNG (FT): %d\n",
|
||||
Mptr->RRVR[i].Min_visRange);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if( Mptr->DVR.visRange != MAXINT )
|
||||
printf("DISPATCH VIS RANGE : %d\n",
|
||||
Mptr->DVR.visRange);
|
||||
|
||||
if( Mptr->DVR.vrbl_visRange )
|
||||
printf("VRBL DISPATCH VISRNG: TRUE\n");
|
||||
|
||||
if( Mptr->DVR.below_min_DVR )
|
||||
printf("BELOW MIN DVR : TRUE\n");
|
||||
|
||||
if( Mptr->DVR.above_max_DVR )
|
||||
printf("ABOVE MAX DVR : TRUE\n");
|
||||
|
||||
if( Mptr->DVR.Max_visRange != MAXINT )
|
||||
printf("MX DSPAT VISRNG (FT): %d\n",
|
||||
Mptr->DVR.Max_visRange);
|
||||
|
||||
if( Mptr->DVR.Min_visRange != MAXINT )
|
||||
printf("MN DSPAT VISRNG (FT): %d\n",
|
||||
Mptr->DVR.Min_visRange);
|
||||
|
||||
|
||||
i = 0;
|
||||
while ( Mptr->WxObstruct[i][0] != '\0' && i < MAXWXSYMBOLS )
|
||||
{
|
||||
printf("WX/OBSTRUCT VISION : %s\n",
|
||||
Mptr->WxObstruct[i] );
|
||||
i++;
|
||||
}
|
||||
|
||||
if( Mptr->PartialObscurationAmt[0][0] != '\0' )
|
||||
printf("OBSCURATION AMOUNT : %s\n",
|
||||
&(Mptr->PartialObscurationAmt[0][0]));
|
||||
|
||||
if( Mptr->PartialObscurationPhenom[0][0] != '\0' )
|
||||
printf("OBSCURATION PHENOM : %s\n",
|
||||
&(Mptr->PartialObscurationPhenom[0][0]));
|
||||
|
||||
|
||||
if( Mptr->PartialObscurationAmt[1][0] != '\0' )
|
||||
printf("OBSCURATION AMOUNT : %s\n",
|
||||
&(Mptr->PartialObscurationAmt[1][0]));
|
||||
|
||||
if( Mptr->PartialObscurationPhenom[1][0] != '\0' )
|
||||
printf("OBSCURATION PHENOM : %s\n",
|
||||
&(Mptr->PartialObscurationPhenom[1][0]));
|
||||
|
||||
i = 0;
|
||||
while ( Mptr->cldTypHgt[ i ].cloud_type[0] != '\0' &&
|
||||
i < 6 )
|
||||
{
|
||||
if( Mptr->cldTypHgt[ i ].cloud_type[0] != '\0' )
|
||||
printf("CLOUD COVER : %s\n",
|
||||
Mptr->cldTypHgt[ i ].cloud_type);
|
||||
|
||||
if( Mptr->cldTypHgt[ i ].cloud_hgt_char[0] != '\0' )
|
||||
printf("CLOUD HGT (CHARAC.) : %s\n",
|
||||
Mptr->cldTypHgt[ i ].cloud_hgt_char);
|
||||
|
||||
if( Mptr->cldTypHgt[ i ].cloud_hgt_meters != MAXINT)
|
||||
printf("CLOUD HGT (METERS) : %d\n",
|
||||
Mptr->cldTypHgt[ i ].cloud_hgt_meters);
|
||||
|
||||
if( Mptr->cldTypHgt[ i ].other_cld_phenom[0] != '\0' )
|
||||
printf("OTHER CLOUD PHENOM : %s\n",
|
||||
Mptr->cldTypHgt[ i ].other_cld_phenom);
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
if( Mptr->temp != MAXINT )
|
||||
printf("TEMP. (CELSIUS) : %d\n", Mptr->temp);
|
||||
|
||||
if( Mptr->dew_pt_temp != MAXINT )
|
||||
printf("D.P. TEMP. (CELSIUS): %d\n", Mptr->dew_pt_temp);
|
||||
|
||||
if( Mptr->A_altstng )
|
||||
printf("ALTIMETER (INCHES) : %.2f\n",
|
||||
Mptr->inches_altstng );
|
||||
|
||||
if( Mptr->Q_altstng )
|
||||
printf("ALTIMETER (PASCALS) : %d\n",
|
||||
Mptr->hectoPasc_altstng );
|
||||
|
||||
if( Mptr->TornadicType[0] != '\0' )
|
||||
printf("TORNADIC ACTVTY TYPE: %s\n",
|
||||
Mptr->TornadicType );
|
||||
|
||||
if( Mptr->BTornadicHour != MAXINT )
|
||||
printf("TORN. ACTVTY BEGHOUR: %d\n",
|
||||
Mptr->BTornadicHour );
|
||||
|
||||
if( Mptr->BTornadicMinute != MAXINT )
|
||||
printf("TORN. ACTVTY BEGMIN : %d\n",
|
||||
Mptr->BTornadicMinute );
|
||||
|
||||
if( Mptr->ETornadicHour != MAXINT )
|
||||
printf("TORN. ACTVTY ENDHOUR: %d\n",
|
||||
Mptr->ETornadicHour );
|
||||
|
||||
if( Mptr->ETornadicMinute != MAXINT )
|
||||
printf("TORN. ACTVTY ENDMIN : %d\n",
|
||||
Mptr->ETornadicMinute );
|
||||
|
||||
if( Mptr->TornadicDistance != MAXINT )
|
||||
printf("TORN. DIST. FROM STN: %d\n",
|
||||
Mptr->TornadicDistance );
|
||||
|
||||
if( Mptr->TornadicLOC[0] != '\0' )
|
||||
printf("TORNADIC LOCATION : %s\n",
|
||||
Mptr->TornadicLOC );
|
||||
|
||||
if( Mptr->TornadicDIR[0] != '\0' )
|
||||
printf("TORNAD. DIR FROM STN: %s\n",
|
||||
Mptr->TornadicDIR );
|
||||
|
||||
if( Mptr->TornadicMovDir[0] != '\0' )
|
||||
printf("TORNADO DIR OF MOVM.: %s\n",
|
||||
Mptr->TornadicMovDir );
|
||||
|
||||
|
||||
if( Mptr->autoIndicator[0] != '\0' )
|
||||
printf("AUTO INDICATOR : %s\n",
|
||||
Mptr->autoIndicator);
|
||||
|
||||
if( Mptr->PKWND_dir != MAXINT )
|
||||
printf("PEAK WIND DIRECTION : %d\n",Mptr->PKWND_dir);
|
||||
if( Mptr->PKWND_speed != MAXINT )
|
||||
printf("PEAK WIND SPEED : %d\n",Mptr->PKWND_speed);
|
||||
if( Mptr->PKWND_hour != MAXINT )
|
||||
printf("PEAK WIND HOUR : %d\n",Mptr->PKWND_hour);
|
||||
if( Mptr->PKWND_minute != MAXINT )
|
||||
printf("PEAK WIND MINUTE : %d\n",Mptr->PKWND_minute);
|
||||
|
||||
if( Mptr->WshfTime_hour != MAXINT )
|
||||
printf("HOUR OF WIND SHIFT : %d\n",Mptr->WshfTime_hour);
|
||||
if( Mptr->WshfTime_minute != MAXINT )
|
||||
printf("MINUTE OF WIND SHIFT: %d\n",Mptr->WshfTime_minute);
|
||||
if( Mptr->Wshft_FROPA != FALSE )
|
||||
printf("FROPA ASSOC. W/WSHFT: TRUE\n");
|
||||
|
||||
if( Mptr->TWR_VSBY != (float) MAXINT )
|
||||
printf("TOWER VISIBILITY : %.2f\n",Mptr->TWR_VSBY);
|
||||
if( Mptr->SFC_VSBY != (float) MAXINT )
|
||||
printf("SURFACE VISIBILITY : %.2f\n",Mptr->SFC_VSBY);
|
||||
|
||||
if( Mptr->minVsby != (float) MAXINT )
|
||||
printf("MIN VRBL_VIS (SM) : %.4f\n",Mptr->minVsby);
|
||||
if( Mptr->maxVsby != (float) MAXINT )
|
||||
printf("MAX VRBL_VIS (SM) : %.4f\n",Mptr->maxVsby);
|
||||
|
||||
if( Mptr->VSBY_2ndSite != (float) MAXINT )
|
||||
printf("VSBY_2ndSite (SM) : %.4f\n",Mptr->VSBY_2ndSite);
|
||||
if( Mptr->VSBY_2ndSite_LOC[0] != '\0' )
|
||||
printf("VSBY_2ndSite LOC. : %s\n",
|
||||
Mptr->VSBY_2ndSite_LOC);
|
||||
|
||||
|
||||
if( Mptr->OCNL_LTG )
|
||||
printf("OCCASSIONAL LTG : TRUE\n");
|
||||
|
||||
if( Mptr->FRQ_LTG )
|
||||
printf("FREQUENT LIGHTNING : TRUE\n");
|
||||
|
||||
if( Mptr->CNS_LTG )
|
||||
printf("CONTINUOUS LTG : TRUE\n");
|
||||
|
||||
if( Mptr->CG_LTG )
|
||||
printf("CLOUD-GROUND LTG : TRUE\n");
|
||||
|
||||
if( Mptr->IC_LTG )
|
||||
printf("IN-CLOUD LIGHTNING : TRUE\n");
|
||||
|
||||
if( Mptr->CC_LTG )
|
||||
printf("CLD-CLD LIGHTNING : TRUE\n");
|
||||
|
||||
if( Mptr->CA_LTG )
|
||||
printf("CLOUD-AIR LIGHTNING : TRUE\n");
|
||||
|
||||
if( Mptr->AP_LTG )
|
||||
printf("LIGHTNING AT AIRPORT: TRUE\n");
|
||||
|
||||
if( Mptr->OVHD_LTG )
|
||||
printf("LIGHTNING OVERHEAD : TRUE\n");
|
||||
|
||||
if( Mptr->DSNT_LTG )
|
||||
printf("DISTANT LIGHTNING : TRUE\n");
|
||||
|
||||
if( Mptr->LightningVCTS )
|
||||
printf("L'NING W/I 5-10(ALP): TRUE\n");
|
||||
|
||||
if( Mptr->LightningTS )
|
||||
printf("L'NING W/I 5 (ALP) : TRUE\n");
|
||||
|
||||
if( Mptr->VcyStn_LTG )
|
||||
printf("VCY STN LIGHTNING : TRUE\n");
|
||||
|
||||
if( Mptr->LTG_DIR[0] != '\0' )
|
||||
printf("DIREC. OF LIGHTNING : %s\n", Mptr->LTG_DIR);
|
||||
|
||||
|
||||
|
||||
i = 0;
|
||||
while( i < 3 && Mptr->ReWx[ i ].Recent_weather[0] != '\0' )
|
||||
{
|
||||
printf("RECENT WEATHER : %s",
|
||||
Mptr->ReWx[i].Recent_weather);
|
||||
|
||||
if( Mptr->ReWx[i].Bhh != MAXINT )
|
||||
printf(" BEG_hh = %d",Mptr->ReWx[i].Bhh);
|
||||
if( Mptr->ReWx[i].Bmm != MAXINT )
|
||||
printf(" BEG_mm = %d",Mptr->ReWx[i].Bmm);
|
||||
|
||||
if( Mptr->ReWx[i].Ehh != MAXINT )
|
||||
printf(" END_hh = %d",Mptr->ReWx[i].Ehh);
|
||||
if( Mptr->ReWx[i].Emm != MAXINT )
|
||||
printf(" END_mm = %d",Mptr->ReWx[i].Emm);
|
||||
|
||||
printf("\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if( Mptr->minCeiling != MAXINT )
|
||||
printf("MIN VRBL_CIG (FT) : %d\n",Mptr->minCeiling);
|
||||
if( Mptr->maxCeiling != MAXINT )
|
||||
printf("MAX VRBL_CIG (FT)) : %d\n",Mptr->maxCeiling);
|
||||
|
||||
if( Mptr->CIG_2ndSite_Meters != MAXINT )
|
||||
printf("CIG2ndSite (FT) : %d\n",Mptr->CIG_2ndSite_Meters);
|
||||
if( Mptr->CIG_2ndSite_LOC[0] != '\0' )
|
||||
printf("CIG @ 2nd Site LOC. : %s\n",Mptr->CIG_2ndSite_LOC);
|
||||
|
||||
if( Mptr->PRESFR )
|
||||
printf("PRESFR : TRUE\n");
|
||||
if( Mptr->PRESRR )
|
||||
printf("PRESRR : TRUE\n");
|
||||
|
||||
if( Mptr->SLPNO )
|
||||
printf("SLPNO : TRUE\n");
|
||||
|
||||
if( Mptr->SLP != (float) MAXINT )
|
||||
printf("SLP (hPa) : %.1f\n", Mptr->SLP);
|
||||
|
||||
if( Mptr->SectorVsby != (float) MAXINT )
|
||||
printf("SECTOR VSBY (MILES) : %.2f\n", Mptr->SectorVsby );
|
||||
|
||||
if( Mptr->SectorVsby_Dir[ 0 ] != '\0' )
|
||||
printf("SECTOR VSBY OCTANT : %s\n", Mptr->SectorVsby_Dir );
|
||||
|
||||
if( Mptr->TS_LOC[ 0 ] != '\0' )
|
||||
printf("THUNDERSTORM LOCAT. : %s\n", Mptr->TS_LOC );
|
||||
|
||||
if( Mptr->TS_MOVMNT[ 0 ] != '\0' )
|
||||
printf("THUNDERSTORM MOVMNT.: %s\n", Mptr->TS_MOVMNT);
|
||||
|
||||
if( Mptr->GR )
|
||||
printf("GR (HAILSTONES) : TRUE\n");
|
||||
|
||||
if( Mptr->GR_Size != (float) MAXINT )
|
||||
printf("HLSTO SIZE (INCHES) : %.3f\n",Mptr->GR_Size);
|
||||
|
||||
if( Mptr->VIRGA )
|
||||
printf("VIRGA : TRUE\n");
|
||||
|
||||
if( Mptr->VIRGA_DIR[0] != '\0' )
|
||||
printf("DIR OF VIRGA FRM STN: %s\n", Mptr->VIRGA_DIR);
|
||||
|
||||
for( i = 0; i < 6; i++ ) {
|
||||
if( Mptr->SfcObscuration[i][0] != '\0' )
|
||||
printf("SfcObscuration : %s\n",
|
||||
&(Mptr->SfcObscuration[i][0]) );
|
||||
}
|
||||
|
||||
if( Mptr->Num8thsSkyObscured != MAXINT )
|
||||
printf("8ths of SkyObscured : %d\n",Mptr->Num8thsSkyObscured);
|
||||
|
||||
if( Mptr->CIGNO )
|
||||
printf("CIGNO : TRUE\n");
|
||||
|
||||
if( Mptr->Ceiling != MAXINT )
|
||||
printf("Ceiling (ft) : %d\n",Mptr->Ceiling);
|
||||
|
||||
if( Mptr->Estimated_Ceiling != MAXINT )
|
||||
printf("Estimated CIG (ft) : %d\n",Mptr->Estimated_Ceiling);
|
||||
|
||||
if( Mptr->VrbSkyBelow[0] != '\0' )
|
||||
printf("VRB SKY COND BELOW : %s\n",Mptr->VrbSkyBelow);
|
||||
|
||||
if( Mptr->VrbSkyAbove[0] != '\0' )
|
||||
printf("VRB SKY COND ABOVE : %s\n",Mptr->VrbSkyAbove);
|
||||
|
||||
if( Mptr->VrbSkyLayerHgt != MAXINT )
|
||||
printf("VRBSKY COND HGT (FT): %d\n",Mptr->VrbSkyLayerHgt);
|
||||
|
||||
if( Mptr->ObscurAloftHgt != MAXINT )
|
||||
printf("Hgt Obscur Aloft(ft): %d\n",Mptr->ObscurAloftHgt);
|
||||
|
||||
if( Mptr->ObscurAloft[0] != '\0' )
|
||||
printf("Obscur Phenom Aloft : %s\n",Mptr->ObscurAloft);
|
||||
|
||||
if( Mptr->ObscurAloftSkyCond[0] != '\0' )
|
||||
printf("Obscur ALOFT SKYCOND: %s\n",Mptr->ObscurAloftSkyCond);
|
||||
|
||||
|
||||
if( Mptr->NOSPECI )
|
||||
printf("NOSPECI : TRUE\n");
|
||||
|
||||
if( Mptr->LAST )
|
||||
printf("LAST : TRUE\n");
|
||||
|
||||
if( Mptr->synoptic_cloud_type[ 0 ] != '\0' )
|
||||
printf("SYNOPTIC CLOUD GROUP: %s\n",Mptr->synoptic_cloud_type);
|
||||
|
||||
if( Mptr->CloudLow != '\0' )
|
||||
printf("LOW CLOUD CODE : %c\n",Mptr->CloudLow);
|
||||
|
||||
if( Mptr->CloudMedium != '\0' )
|
||||
printf("MEDIUM CLOUD CODE : %c\n",Mptr->CloudMedium);
|
||||
|
||||
if( Mptr->CloudHigh != '\0' )
|
||||
printf("HIGH CLOUD CODE : %c\n",Mptr->CloudHigh);
|
||||
|
||||
if( Mptr->SNINCR != MAXINT )
|
||||
printf("SNINCR (INCHES) : %d\n",Mptr->SNINCR);
|
||||
|
||||
if( Mptr->SNINCR_TotalDepth != MAXINT )
|
||||
printf("SNINCR(TOT. INCHES) : %d\n",Mptr->SNINCR_TotalDepth);
|
||||
|
||||
if( Mptr->snow_depth_group[ 0 ] != '\0' )
|
||||
printf("SNOW DEPTH GROUP : %s\n",Mptr->snow_depth_group);
|
||||
|
||||
if( Mptr->snow_depth != MAXINT )
|
||||
printf("SNOW DEPTH (INCHES) : %d\n",Mptr->snow_depth);
|
||||
|
||||
if( Mptr->WaterEquivSnow != (float) MAXINT )
|
||||
printf("H2O EquivSno(inches): %.2f\n",Mptr->WaterEquivSnow);
|
||||
|
||||
if( Mptr->SunshineDur != MAXINT )
|
||||
printf("SUNSHINE (MINUTES) : %d\n",Mptr->SunshineDur);
|
||||
|
||||
if( Mptr->SunSensorOut )
|
||||
printf("SUN SENSOR OUT : TRUE\n");
|
||||
|
||||
if( Mptr->hourlyPrecip != (float) MAXINT )
|
||||
printf("HRLY PRECIP (INCHES): %.2f\n",Mptr->hourlyPrecip);
|
||||
|
||||
if( Mptr->precip_amt != (float) MAXINT)
|
||||
printf("3/6HR PRCIP (INCHES): %.2f\n",
|
||||
Mptr->precip_amt);
|
||||
|
||||
if( Mptr->Indeterminant3_6HrPrecip )
|
||||
printf("INDTRMN 3/6HR PRECIP: TRUE\n");
|
||||
|
||||
if( Mptr->precip_24_amt != (float) MAXINT)
|
||||
printf("24HR PRECIP (INCHES): %.2f\n",
|
||||
Mptr->precip_24_amt);
|
||||
|
||||
if( Mptr->Temp_2_tenths != (float) MAXINT )
|
||||
printf("TMP2TENTHS (CELSIUS): %.1f\n",Mptr->Temp_2_tenths);
|
||||
|
||||
if( Mptr->DP_Temp_2_tenths != (float) MAXINT )
|
||||
printf("DPT2TENTHS (CELSIUS): %.1f\n",Mptr->DP_Temp_2_tenths);
|
||||
|
||||
if( Mptr->maxtemp != (float) MAXINT)
|
||||
printf("MAX TEMP (CELSIUS) : %.1f\n",
|
||||
Mptr->maxtemp);
|
||||
|
||||
if( Mptr->mintemp != (float) MAXINT)
|
||||
printf("MIN TEMP (CELSIUS) : %.1f\n",
|
||||
Mptr->mintemp);
|
||||
|
||||
if( Mptr->max24temp != (float) MAXINT)
|
||||
printf("24HrMAXTMP (CELSIUS): %.1f\n",
|
||||
Mptr->max24temp);
|
||||
|
||||
if( Mptr->min24temp != (float) MAXINT)
|
||||
printf("24HrMINTMP (CELSIUS): %.1f\n",
|
||||
Mptr->min24temp);
|
||||
|
||||
if( Mptr->char_prestndcy != MAXINT)
|
||||
printf("CHAR PRESS TENDENCY : %d\n",
|
||||
Mptr->char_prestndcy );
|
||||
|
||||
if( Mptr->prestndcy != (float) MAXINT)
|
||||
printf("PRES. TENDENCY (hPa): %.1f\n",
|
||||
Mptr->prestndcy );
|
||||
|
||||
if( Mptr->PWINO )
|
||||
printf("PWINO : TRUE\n");
|
||||
|
||||
if( Mptr->PNO )
|
||||
printf("PNO : TRUE\n");
|
||||
|
||||
if( Mptr->CHINO )
|
||||
printf("CHINO : TRUE\n");
|
||||
|
||||
if( Mptr->CHINO_LOC[0] != '\0' )
|
||||
printf("CHINO_LOC : %s\n",Mptr->CHINO_LOC);
|
||||
|
||||
if( Mptr->VISNO )
|
||||
printf("VISNO : TRUE\n");
|
||||
|
||||
if( Mptr->VISNO_LOC[0] != '\0' )
|
||||
printf("VISNO_LOC : %s\n",Mptr->VISNO_LOC);
|
||||
|
||||
if( Mptr->FZRANO )
|
||||
printf("FZRANO : TRUE\n");
|
||||
|
||||
if( Mptr->TSNO )
|
||||
printf("TSNO : TRUE\n");
|
||||
|
||||
if( Mptr->DollarSign)
|
||||
printf("DOLLAR $IGN INDCATR : TRUE\n");
|
||||
|
||||
if( Mptr->horiz_vsby[ 0 ] != '\0' )
|
||||
printf("HORIZ VISIBILITY : %s\n",Mptr->horiz_vsby);
|
||||
|
||||
if( Mptr->dir_min_horiz_vsby[ 0 ] != '\0' )
|
||||
printf("DIR MIN HORIZ VSBY : %s\n",Mptr->dir_min_horiz_vsby);
|
||||
|
||||
if( Mptr->CAVOK )
|
||||
printf("CAVOK : TRUE\n");
|
||||
|
||||
|
||||
if( Mptr->VertVsby != MAXINT )
|
||||
printf("Vert. Vsby (meters) : %d\n",
|
||||
Mptr->VertVsby );
|
||||
|
||||
if( Mptr->charVertVsby[0] != '\0' )
|
||||
printf("Vert. Vsby (CHAR) : %s\n",
|
||||
Mptr->charVertVsby );
|
||||
|
||||
if( Mptr->QFE != MAXINT )
|
||||
printf("QFE : %d\n", Mptr->QFE);
|
||||
|
||||
if( Mptr->VOLCASH )
|
||||
printf("VOLCANIC ASH : TRUE\n");
|
||||
|
||||
if( Mptr->min_vrbl_wind_dir != MAXINT )
|
||||
printf("MIN VRBL WIND DIR : %d\n",Mptr->min_vrbl_wind_dir);
|
||||
if( Mptr->max_vrbl_wind_dir != MAXINT )
|
||||
printf("MAX VRBL WIND DIR : %d\n",Mptr->max_vrbl_wind_dir);
|
||||
|
||||
|
||||
printf("\n\n\n");
|
||||
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
There are 2 classes: CMetarStation (MetarStation.h) and CMetarReport
|
||||
(MetarReport.h). These classes provide mechanisms to get information
|
||||
about meteorological data reporting stations and about the reports
|
||||
themselves. These stations and reports are known as METAR. See
|
||||
http://tgsv5.nws.noaa.gov/oso/oso1/oso12/metar.htm for information
|
||||
from the USA perspective. Quoting from that site:
|
||||
|
||||
On 1 July 1996, the international standard code for hourly and special
|
||||
surface weather observations, METAR/SPECI, took effect.
|
||||
The METAR acronym roughly translates from the French as Aviation
|
||||
Routine Weather Report . A special report, SPECI, is merely a METAR
|
||||
formatted report which is issued on a non-routine basis as dictated by
|
||||
changing meteorological conditions. The SPECI acronym roughly translates as
|
||||
|
||||
Aviation Selected Special Weather Report . Meanwhile, the international
|
||||
standard code format for terminal forecasts issued for airports, TAF,
|
||||
also took effect. The acronym translates to Aerodrome Forecast.
|
||||
|
||||
This implementation ignores the SPECI and TAF acronyms, calling the
|
||||
entire system METAR.
|
||||
|
||||
The class CMetarStation is implemented by MetarStation.h and
|
||||
MetarStation.cpp. It decodes a text file containing information about
|
||||
individual METAR reporting stations and builds a static database of that
|
||||
information during static construction of the class. There are static
|
||||
member methods to find individual stations, and member functions to
|
||||
extract individual station attributes. The information about METAR
|
||||
stations probably has some overlap with FGFS airport information. That
|
||||
needs to be investigated. The METAR station information is kept in this
|
||||
file:
|
||||
http://www.nws.noaa.gov/pub/stninfo/nsd_cccc.gz
|
||||
http://www.nws.noaa.gov/pub/stninfo/nsd_cccc.txt
|
||||
This class looks for the file FG_ROOT/Weather/MetarStations instead of
|
||||
nsd_cccc.
|
||||
The current implementation does not look for updates to this file on the
|
||||
internet.
|
||||
|
||||
The class CMetarReport is implemented by MetarReport.h and MetarReport.cpp.
|
||||
It encapsulates the decoding software written by Carl McCalla at -
|
||||
NOAA/National Weather Service
|
||||
1325 East-West Highway
|
||||
SSMC2, W/OSO242, Station 5114
|
||||
Silver Spring, Maryland 20910
|
||||
Work: (301) 713-0882, Ext 115
|
||||
FAX: (301) 608-0911
|
||||
E-Mail Address: cmccalla@smtpgate.ssmc.noaa.gov
|
||||
http://www.nws.noaa.gov/software/
|
||||
This software generally sucks and the CMetarReport class attempts to clean
|
||||
up some of that suckiness. A CMetarReport object is created with an ASCII
|
||||
string as a construction parameter. The string contains a METAR report.
|
||||
There
|
||||
are member methods to extract selected information from a report by calling
|
||||
the McCalla software. Additional information can be selected by adding new
|
||||
member methods as needed. Certainly the methods currently implemented are
|
||||
not sufficient. METAR reports are available via the internet. In the USA,
|
||||
NOAA provides individual METAR reports in this directory:
|
||||
ftp://weather.noaa.gov/data/observations/metar/stations
|
||||
Other sources are available as well. The current implementation does not
|
||||
look for reports on the internet.
|
||||
|
||||
There is a test program in the MetarTest subdirectory. It requires that a
|
||||
#define be changed in the MetarStation.cpp file. Add #define TESTPROG to
|
||||
the code or -D TESTPROG to the compilation. This is necessary because the
|
||||
FGFS options class is coupled tightly to code that shouldn't be pulled into
|
||||
the test program. The test program will decode many METAR reports and
|
||||
display
|
||||
them to the screen, then it will plot all the METAR reporting stations on a
|
||||
tumbling globe.
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
#include "Local.h" /* standard header file */
|
||||
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* Title: stspack2 */
|
||||
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
|
||||
/* Date: 05 Oct 1992 */
|
||||
/* Programmer: ALLAN DARLING */
|
||||
/* Language: C/2 */
|
||||
/* */
|
||||
/* Abstract: The stspack2 package contains functions to */
|
||||
/* perform the isalnum through isxdigit functions */
|
||||
/* on strings. The functions come in four forms: */
|
||||
/* those that test NULL delimited strings and are */
|
||||
/* named in the form sxxxxxxx, those that test at */
|
||||
/* most n characters and are named in the form */
|
||||
/* nxxxxxxx, those that search forward in a string */
|
||||
/* and are named in the form nxtyyyyy, and those */
|
||||
/* that search backward in a string and are named */
|
||||
/* in the form lstyyyyy. */
|
||||
/* */
|
||||
/* The xxxxxxx is the name of the test applied to */
|
||||
/* each character in the string, such as isalpha, */
|
||||
/* thus a function to test a NULL delimited string */
|
||||
/* an return a nonzero value if all characters in */
|
||||
/* the string are digits is named sisdigit. */
|
||||
/* */
|
||||
/* The yyyyy is the name of the test applied to */
|
||||
/* characters in a string, minus the 'is' prefix. */
|
||||
/* Thus a function to find the next digit in a NULL */
|
||||
/* delimited string and return a pointer to it is */
|
||||
/* named nxtdigit. */
|
||||
/* */
|
||||
/* The only exception to the naming rule is for the */
|
||||
/* functions that test for hexadecimal digits. */
|
||||
/* These are named sisxdigi, nisxdigi, nxtxdigi, */
|
||||
/* and lstxdigi because of the eight character */
|
||||
/* function name limitation. */
|
||||
/* */
|
||||
/* The nxxxxxxx class of functions will test up to */
|
||||
/* n characters or the first NULL character */
|
||||
/* encountered, whichever comes first. For all */
|
||||
/* classes of functions, the string sentinal is */
|
||||
/* not included in the test. */
|
||||
/* */
|
||||
/* External Functions Called: */
|
||||
/* isalnum, isalpha, iscntrl, isdigit, isgraph, */
|
||||
/* islower, isprint, ispunct, isspace, isupper, */
|
||||
/* isxdigit. */
|
||||
/* */
|
||||
/* Input: For sxxxxxxx class functions, a pointer to a */
|
||||
/* NULL delimited character string. */
|
||||
/* */
|
||||
/* For nxtyyyyy class functions, a pointer to a */
|
||||
/* NULL delimited character string. */
|
||||
/* */
|
||||
/* for nxxxxxxx class functions, a pointer to a */
|
||||
/* character array, and a positive, nonzero integer.*/
|
||||
/* */
|
||||
/* for lstyyyyy class functions, a pointer to a */
|
||||
/* character array, and a positive, nonzero integer.*/
|
||||
/* */
|
||||
/* Output: A nonzero value if the test is true for all */
|
||||
/* characters in the string, a zero value otherwise.*/
|
||||
/* */
|
||||
/* Modification History: */
|
||||
/* None. */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
|
||||
int nisalnum(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!isalnum(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nisalnum */
|
||||
|
||||
|
||||
int nisalpha(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!isalpha(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nisalpha */
|
||||
|
||||
|
||||
int niscntrl(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!iscntrl(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end niscntrl */
|
||||
|
||||
|
||||
int nisdigit(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!isdigit(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nisdigit */
|
||||
|
||||
|
||||
int nisgraph(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!isgraph(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nisgraph */
|
||||
|
||||
|
||||
int nislower(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!islower(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nislower */
|
||||
|
||||
|
||||
int nisprint(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!isprint(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nisprint */
|
||||
|
||||
|
||||
int nispunct(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!ispunct(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nispunct */
|
||||
|
||||
|
||||
int nisspace(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!isspace(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nisspace */
|
||||
|
||||
|
||||
int nisupper(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!isupper(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nisupper */
|
||||
|
||||
|
||||
int nisxdigi(char *s, int n) {
|
||||
|
||||
for (; *s && n; s++, n--)
|
||||
|
||||
if (!isxdigit(*s))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
|
||||
} /* end nisxdigi */
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
#include "Local.h" /* standard header file */
|
||||
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* Title: stspack3 */
|
||||
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
|
||||
/* Date: 05 Oct 1992 */
|
||||
/* Programmer: ALLAN DARLING */
|
||||
/* Language: C/2 */
|
||||
/* */
|
||||
/* Abstract: The stspack3 package contains functions to */
|
||||
/* perform the isalnum through isxdigit functions */
|
||||
/* on strings. The functions come in four forms: */
|
||||
/* those that test NULL delimited strings and are */
|
||||
/* named in the form sxxxxxxx, those that test at */
|
||||
/* most n characters and are named in the form */
|
||||
/* nxxxxxxx, those that search forward in a string */
|
||||
/* and are named in the form nxtyyyyy, and those */
|
||||
/* that search backward in a string and are named */
|
||||
/* in the form lstyyyyy. */
|
||||
/* */
|
||||
/* The xxxxxxx is the name of the test applied to */
|
||||
/* each character in the string, such as isalpha, */
|
||||
/* thus a function to test a NULL delimited string */
|
||||
/* an return a nonzero value if all characters in */
|
||||
/* the string are digits is named sisdigit. */
|
||||
/* */
|
||||
/* The yyyyy is the name of the test applied to */
|
||||
/* characters in a string, minus the 'is' prefix. */
|
||||
/* Thus a function to find the next digit in a NULL */
|
||||
/* delimited string and return a pointer to it is */
|
||||
/* named nxtdigit. */
|
||||
/* */
|
||||
/* The only exception to the naming rule is for the */
|
||||
/* functions that test for hexadecimal digits. */
|
||||
/* These are named sisxdigi, nisxdigi, nxtxdigi, */
|
||||
/* and lstxdigi because of the eight character */
|
||||
/* function name limitation. */
|
||||
/* */
|
||||
/* The nxxxxxxx class of functions will test up to */
|
||||
/* n characters or the first NULL character */
|
||||
/* encountered, whichever comes first. For all */
|
||||
/* classes of functions, the string sentinal is */
|
||||
/* not included in the test. */
|
||||
/* */
|
||||
/* External Functions Called: */
|
||||
/* isalnum, isalpha, iscntrl, isdigit, isgraph, */
|
||||
/* islower, isprint, ispunct, isspace, isupper, */
|
||||
/* isxdigit. */
|
||||
/* */
|
||||
/* Input: For sxxxxxxx class functions, a pointer to a */
|
||||
/* NULL delimited character string. */
|
||||
/* */
|
||||
/* For nxtyyyyy class functions, a pointer to a */
|
||||
/* NULL delimited character string. */
|
||||
/* */
|
||||
/* for nxxxxxxx class functions, a pointer to a */
|
||||
/* character array, and a positive, nonzero integer.*/
|
||||
/* */
|
||||
/* for lstyyyyy class functions, a pointer to a */
|
||||
/* character array, and a positive, nonzero integer.*/
|
||||
/* */
|
||||
/* Output: A nonzero value if the test is true for all */
|
||||
/* characters in the string, a zero value otherwise.*/
|
||||
/* */
|
||||
/* Modification History: */
|
||||
/* None. */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
char *nxtalnum(char *s) {
|
||||
|
||||
for (; !isalnum(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtalnum */
|
||||
|
||||
|
||||
char *nxtalpha(char *s) {
|
||||
|
||||
for (; !isalpha(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtalpha */
|
||||
|
||||
|
||||
char *nxtcntrl(char *s) {
|
||||
|
||||
for (; !iscntrl(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtcntrl */
|
||||
|
||||
|
||||
char *nxtdigit(char *s) {
|
||||
|
||||
for (; !isdigit(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtdigit */
|
||||
|
||||
|
||||
char *nxtgraph(char *s) {
|
||||
|
||||
for (; !isgraph(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtgraph */
|
||||
|
||||
|
||||
char *nxtlower(char *s) {
|
||||
|
||||
for (; !islower(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtlower */
|
||||
|
||||
|
||||
char *nxtprint(char *s) {
|
||||
|
||||
for (; !isprint(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtprint */
|
||||
|
||||
|
||||
char *nxtpunct(char *s) {
|
||||
|
||||
for (; !ispunct(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtpunct */
|
||||
|
||||
|
||||
char *nxtspace(char *s) {
|
||||
|
||||
for (; !isspace(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtspace */
|
||||
|
||||
|
||||
char *nxtupper(char *s) {
|
||||
|
||||
for (; !isupper(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtupper */
|
||||
|
||||
|
||||
char *nxtxdigi(char *s) {
|
||||
|
||||
for (; !isxdigit(*s) && *s; s++) ;
|
||||
|
||||
if (*s)
|
||||
return (s);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
} /* end nxtxdigi */
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ include_HEADERS = \
|
||||
strutils.hxx \
|
||||
tabbed_values.hxx \
|
||||
texcoord.hxx \
|
||||
zfstream.hxx
|
||||
zfstream.hxx \
|
||||
interpolator.hxx
|
||||
|
||||
libsgmisc_a_SOURCES = \
|
||||
sg_path.cxx \
|
||||
@@ -17,7 +18,8 @@ libsgmisc_a_SOURCES = \
|
||||
strutils.cxx \
|
||||
tabbed_values.cxx \
|
||||
texcoord.cxx \
|
||||
zfstream.cxx
|
||||
zfstream.cxx \
|
||||
interpolator.cxx
|
||||
|
||||
noinst_PROGRAMS = tabbed_value_test
|
||||
|
||||
|
||||
107
simgear/misc/interpolator.cxx
Normal file
107
simgear/misc/interpolator.cxx
Normal file
@@ -0,0 +1,107 @@
|
||||
// Written by Andrew J. Ross, started December 2003
|
||||
//
|
||||
// Copyright (C) 2003 Andrew J. Ross - andy@plausible.org
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "interpolator.hxx"
|
||||
|
||||
void SGInterpolator::addNew(SGPropertyNode* prop, int nPoints)
|
||||
{
|
||||
// Set the property type to a double, if it isn't already, and
|
||||
// make sure we aren't already managing this node.
|
||||
prop->setDoubleValue(prop->getDoubleValue());
|
||||
cancel(prop);
|
||||
|
||||
Interp* iterp = new Interp();
|
||||
iterp->target = prop;
|
||||
iterp->nPoints = nPoints;
|
||||
iterp->curve = new double[2*nPoints];
|
||||
|
||||
// Dirty trick: leave the new value sitting in _list to avoid
|
||||
// having to return a pointer to a private type.
|
||||
iterp->next = _list;
|
||||
_list = iterp;
|
||||
}
|
||||
|
||||
void SGInterpolator::interpolate(SGPropertyNode* prop, int nPoints,
|
||||
double* values, double* deltas)
|
||||
{
|
||||
addNew(prop, nPoints);
|
||||
for(int i=0; i<nPoints; i++) {
|
||||
_list->dt(i) = deltas[i];
|
||||
_list->val(i) = values[i];
|
||||
}
|
||||
}
|
||||
|
||||
void SGInterpolator::interpolate(SGPropertyNode* prop, double val, double dt)
|
||||
{
|
||||
addNew(prop, 1);
|
||||
_list->dt(0) = dt;
|
||||
_list->val(0) = val;
|
||||
}
|
||||
|
||||
//
|
||||
// Delete all the list elements where "expr" is true.
|
||||
//
|
||||
// Silly preprocessor hack to avoid writing the linked list code in
|
||||
// two places. You would think that an STL set would be the way to
|
||||
// go, but I had terrible trouble getting it to work with the
|
||||
// dynamically allocated "curve" member. Frankly, this is easier to
|
||||
// write, and the code is smaller to boot...
|
||||
//
|
||||
#define DELETE_WHERE(EXPR)\
|
||||
Interp *p = _list, **last = &_list; \
|
||||
while(p) { \
|
||||
if(EXPR) { \
|
||||
*last = p->next; \
|
||||
delete p; \
|
||||
p = (*last) ? (*last)->next : 0; \
|
||||
} else { \
|
||||
last = &(p->next); \
|
||||
p = p->next; } }
|
||||
|
||||
void SGInterpolator::cancel(SGPropertyNode* prop)
|
||||
{
|
||||
DELETE_WHERE(p->target == prop)
|
||||
}
|
||||
|
||||
void SGInterpolator::update(double dt)
|
||||
{
|
||||
DELETE_WHERE(interp(p, dt))
|
||||
}
|
||||
|
||||
// This is the where the only "real" work happens. Walk through the
|
||||
// data points until we find one with some time left, slurp it up and
|
||||
// repeat until we run out of dt.
|
||||
bool SGInterpolator::interp(Interp* rec, double dt)
|
||||
{
|
||||
double val = rec->target->getDoubleValue();
|
||||
int i;
|
||||
for(i=0; i < rec->nPoints; i++) {
|
||||
if(rec->dt(i) > 0 && dt < rec->dt(i)) {
|
||||
val += (dt / rec->dt(i)) * (rec->val(i) - val);
|
||||
rec->dt(i) -= dt;
|
||||
break;
|
||||
}
|
||||
dt -= rec->dt(i);
|
||||
val = rec->val(i);
|
||||
}
|
||||
rec->target->setDoubleValue(val);
|
||||
|
||||
// Return true if this one is done
|
||||
return i == rec->nPoints;
|
||||
}
|
||||
71
simgear/misc/interpolator.hxx
Normal file
71
simgear/misc/interpolator.hxx
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef __SG_INTERPOLATOR_HXX
|
||||
#define __SG_INTERPOLATOR_HXX
|
||||
|
||||
// SGInterpolator
|
||||
// Subsystem that manages smooth linear interpolation of property
|
||||
// values across multiple data points and arbitrary time intervals.
|
||||
|
||||
// Written by Andrew J. Ross, started December 2003
|
||||
//
|
||||
// Copyright (C) 2003 Andrew J. Ross - andy@plausible.org
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
// TODO: support a callback upon interpolation completion so that user
|
||||
// code can register another one immediately without worrying about
|
||||
// timer aliasing.
|
||||
|
||||
class SGInterpolator : public SGSubsystem {
|
||||
public:
|
||||
SGInterpolator() { _list = 0; }
|
||||
virtual void init() {}
|
||||
virtual void update(double delta_time_sec);
|
||||
|
||||
// Simple method that interpolates a double property value from
|
||||
// its current value (default of zero) to the specified target
|
||||
// over the specified time.
|
||||
void interpolate(SGPropertyNode* prop, double value, double dt_sec);
|
||||
|
||||
// More elaborate version that takes a pointer to lists of
|
||||
// arbitrary size.
|
||||
void interpolate(SGPropertyNode* prop, int nPoints,
|
||||
double* values, double* deltas);
|
||||
|
||||
// Cancels any interpolation of the specified property, leaving
|
||||
// its value at the current (mid-interpolation) state.
|
||||
void cancel(SGPropertyNode* prop);
|
||||
|
||||
private:
|
||||
struct Interp {
|
||||
SGPropertyNode_ptr target;
|
||||
int nPoints;
|
||||
double* curve; // time0, val0, time1, val1, ...
|
||||
Interp* next;
|
||||
|
||||
~Interp() { delete[] curve; }
|
||||
double& dt(int i) { return curve[2*i]; }
|
||||
double& val(int i) { return curve[2*i + 1]; }
|
||||
};
|
||||
Interp* _list;
|
||||
|
||||
bool interp(Interp* rec, double dt);
|
||||
void addNew(SGPropertyNode* prop, int nPoints);
|
||||
};
|
||||
|
||||
#endif // __SG_INTERPOLATOR_HXX
|
||||
@@ -40,10 +40,10 @@ static const char sgDirPathSep = ':';
|
||||
static const char sgDirPathSepBad = '/';
|
||||
#else
|
||||
static const char sgDirPathSep = '/';
|
||||
static const char sgDirPathSepBad = ':';
|
||||
static const char sgDirPathSepBad = '\\';
|
||||
#endif
|
||||
|
||||
#if defined( WIN32 )
|
||||
#if defined( WIN32 ) && !defined(__CYGWIN__)
|
||||
static const char sgSearchPathSep = ';';
|
||||
#else
|
||||
static const char sgSearchPathSep = ':';
|
||||
@@ -112,6 +112,11 @@ void SGPath::append( const string& p ) {
|
||||
fix();
|
||||
}
|
||||
|
||||
//add a new path component to the existing path string
|
||||
void SGPath::add( const string& p ) {
|
||||
append( sgSearchPathSep+p );
|
||||
}
|
||||
|
||||
|
||||
// concatenate a string to the end of the path without inserting a
|
||||
// path separator
|
||||
@@ -149,7 +154,7 @@ string SGPath::dir() const {
|
||||
// get the base part of the path (everything but the extension.)
|
||||
string SGPath::base() const {
|
||||
int index = path.rfind(".");
|
||||
if (index >= 0) {
|
||||
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
||||
return path.substr(0, index);
|
||||
} else {
|
||||
return "";
|
||||
@@ -157,9 +162,11 @@ string SGPath::base() const {
|
||||
}
|
||||
|
||||
// get the extention (everything after the final ".")
|
||||
// but make sure no "/" follows the "." character (otherwise it
|
||||
// is has to be a directory name containing a ".").
|
||||
string SGPath::extension() const {
|
||||
int index = path.rfind(".");
|
||||
if (index >= 0) {
|
||||
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
||||
return path.substr(index + 1);
|
||||
} else {
|
||||
return "";
|
||||
@@ -189,7 +196,8 @@ string_list sgPathSplit( const string &search_path ) {
|
||||
result.push_back( tmp.substr(0, index) );
|
||||
tmp = tmp.substr( index + 1 );
|
||||
} else {
|
||||
result.push_back( tmp );
|
||||
if ( !tmp.empty() )
|
||||
result.push_back( tmp );
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,12 @@ public:
|
||||
* @param p additional path component */
|
||||
void append( const string& p );
|
||||
|
||||
/**
|
||||
* Append a new piece to the existing path. Inserts a search path
|
||||
* separator to the existing path and the new patch component.
|
||||
* @param p additional path component */
|
||||
void add( const string& p );
|
||||
|
||||
/**
|
||||
* Concatenate a string to the end of the path without inserting a
|
||||
* path separator.
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include STL_STRING
|
||||
|
||||
#include <ctype.h> // isspace()
|
||||
|
||||
#ifdef SG_HAVE_STD_INCLUDES
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef SG_TABBED_VALUES_HXX
|
||||
#define SG_TABBED_VALUES_HXX
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include "simgear/compiler.h"
|
||||
#include <vector>
|
||||
#include STL_STRING
|
||||
|
||||
SG_USING_STD(vector);
|
||||
SG_USING_STD(string);
|
||||
|
||||
@@ -141,7 +141,11 @@ public:
|
||||
protected:
|
||||
|
||||
virtual int_type underflow();
|
||||
#ifndef SG_HAVE_STD_INCLUDES
|
||||
virtual int_type overflow( int_type c = traits_type::eof() );
|
||||
#else
|
||||
virtual int_type overflow( int_type c = streambuf::traits_type::eof() );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
|
||||
23
simgear/nasal/Makefile.am
Normal file
23
simgear/nasal/Makefile.am
Normal file
@@ -0,0 +1,23 @@
|
||||
includedir = @includedir@/nasal
|
||||
|
||||
lib_LIBRARIES = libsgnasal.a
|
||||
|
||||
include_HEADERS = nasal.h
|
||||
|
||||
libsgnasal_a_SOURCES = \
|
||||
code.c code.h \
|
||||
codegen.c \
|
||||
data.h \
|
||||
debug.c \
|
||||
gc.c \
|
||||
hash.c \
|
||||
lex.c \
|
||||
lib.c \
|
||||
mathlib.c \
|
||||
misc.c \
|
||||
nasal.h \
|
||||
parse.c parse.h \
|
||||
string.c \
|
||||
vector.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
586
simgear/nasal/code.c
Normal file
586
simgear/nasal/code.c
Normal file
@@ -0,0 +1,586 @@
|
||||
#include "nasal.h"
|
||||
#include "code.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Debugging stuff. ////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DEBUG_NASAL)
|
||||
# define DBG(expr) /* noop */
|
||||
#else
|
||||
# define DBG(expr) expr
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
char* opStringDEBUG(int op);
|
||||
void printOpDEBUG(int ip, int op);
|
||||
void printRefDEBUG(naRef r);
|
||||
void printStackDEBUG(struct Context* ctx);
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FIXME: need to store a list of all contexts
|
||||
struct Context globalContext;
|
||||
|
||||
#define ERR(c, msg) naRuntimeError((c),(msg))
|
||||
void naRuntimeError(struct Context* c, char* msg)
|
||||
{
|
||||
c->error = msg;
|
||||
longjmp(c->jumpHandle, 1);
|
||||
}
|
||||
|
||||
int boolify(struct Context* ctx, naRef r)
|
||||
{
|
||||
if(IS_NIL(r)) return 0;
|
||||
if(IS_NUM(r)) return r.num != 0;
|
||||
if(IS_STR(r)) return 1;
|
||||
ERR(ctx, "non-scalar used in boolean context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double numify(struct Context* ctx, naRef o)
|
||||
{
|
||||
double n;
|
||||
if(IS_NUM(o)) return o.num;
|
||||
else if(IS_NIL(o)) ERR(ctx, "nil used in numeric context");
|
||||
else if(!IS_STR(o)) ERR(ctx, "non-scalar in numeric context");
|
||||
else if(naStr_tonum(o, &n)) return n;
|
||||
else ERR(ctx, "non-numeric string in numeric context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static naRef stringify(struct Context* ctx, naRef r)
|
||||
{
|
||||
if(IS_STR(r)) return r;
|
||||
if(IS_NUM(r)) return naStr_fromnum(naNewString(ctx), r.num);
|
||||
ERR(ctx, "non-scalar in string context");
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static int checkVec(struct Context* ctx, naRef vec, naRef idx)
|
||||
{
|
||||
int i = (int)numify(ctx, idx);
|
||||
if(i < 0 || i >= vec.ref.ptr.vec->size)
|
||||
ERR(ctx, "vector index out of bounds");
|
||||
return i;
|
||||
}
|
||||
|
||||
static naRef containerGet(struct Context* ctx, naRef box, naRef key)
|
||||
{
|
||||
naRef result = naNil();
|
||||
if(!IS_SCALAR(key)) ERR(ctx, "container index not scalar");
|
||||
if(IS_HASH(box)) {
|
||||
if(!naHash_get(box, key, &result))
|
||||
ERR(ctx, "undefined value in container");
|
||||
} else if(IS_VEC(box)) {
|
||||
result = naVec_get(box, checkVec(ctx, box, key));
|
||||
} else {
|
||||
ERR(ctx, "extract from non-container");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void containerSet(struct Context* ctx, naRef box, naRef key, naRef val)
|
||||
{
|
||||
if(!IS_SCALAR(key)) ERR(ctx, "container index not scalar");
|
||||
else if(IS_HASH(box)) naHash_set(box, key, val);
|
||||
else if(IS_VEC(box)) naVec_set(box, checkVec(ctx, box, key), val);
|
||||
else ERR(ctx, "insert into non-container");
|
||||
}
|
||||
|
||||
static void initContext(struct Context* c)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<NUM_NASAL_TYPES; i++)
|
||||
naGC_init(&(c->pools[i]), i);
|
||||
|
||||
c->fTop = c->opTop = c->markTop = 0;
|
||||
|
||||
naBZero(c->fStack, MAX_RECURSION * sizeof(struct Frame));
|
||||
naBZero(c->opStack, MAX_STACK_DEPTH * sizeof(naRef));
|
||||
|
||||
// Make sure the args vectors (which are static with the context)
|
||||
// are initialized to nil.
|
||||
for(i=0; i<MAX_RECURSION; i++)
|
||||
c->fStack[i].args = naNil();
|
||||
|
||||
// Note we can't use naNewVector() for this; it requires that
|
||||
// temps exist first.
|
||||
c->temps = naObj(T_VEC, naGC_get(&(c->pools[T_VEC])));
|
||||
|
||||
c->save = naNil();
|
||||
|
||||
// Cache pre-calculated "me", "arg" and "parents" scalars
|
||||
c->meRef = naStr_fromdata(naNewString(c), "me", 2);
|
||||
c->argRef = naStr_fromdata(naNewString(c), "arg", 3);
|
||||
c->parentsRef = naStr_fromdata(naNewString(c), "parents", 7);
|
||||
}
|
||||
|
||||
struct Context* naNewContext()
|
||||
{
|
||||
// FIXME: need more than one!
|
||||
struct Context* c = &globalContext;
|
||||
initContext(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
void naGarbageCollect()
|
||||
{
|
||||
int i;
|
||||
struct Context* c = &globalContext; // FIXME: more than one!
|
||||
|
||||
for(i=0; i < c->fTop; i++) {
|
||||
naGC_mark(c->fStack[i].func);
|
||||
naGC_mark(c->fStack[i].locals);
|
||||
}
|
||||
for(i=0; i < MAX_RECURSION; i++)
|
||||
naGC_mark(c->fStack[i].args); // collect *all* the argument lists
|
||||
for(i=0; i < c->opTop; i++)
|
||||
naGC_mark(c->opStack[i]);
|
||||
|
||||
naGC_mark(c->temps);
|
||||
naGC_mark(c->save);
|
||||
|
||||
naGC_mark(c->meRef);
|
||||
naGC_mark(c->argRef);
|
||||
naGC_mark(c->parentsRef);
|
||||
|
||||
// Finally collect all the freed objects
|
||||
for(i=0; i<NUM_NASAL_TYPES; i++)
|
||||
naGC_reap(&(c->pools[i]));
|
||||
}
|
||||
|
||||
void setupFuncall(struct Context* ctx, naRef func, naRef args)
|
||||
{
|
||||
struct Frame* f;
|
||||
f = &(ctx->fStack[ctx->fTop++]);
|
||||
f->func = func;
|
||||
f->ip = 0;
|
||||
f->bp = ctx->opTop;
|
||||
f->line = 0;
|
||||
|
||||
DBG(printf("Entering frame %d\n", ctx->fTop-1);)
|
||||
|
||||
if(!IS_REF(func))
|
||||
ERR(ctx, "function/method call invoked on uncallable object");
|
||||
|
||||
f->args = args;
|
||||
if(IS_CCODE(func.ref.ptr.func->code)) {
|
||||
f->locals = naNil();
|
||||
} else if(IS_CODE(func.ref.ptr.func->code)) {
|
||||
f->locals = naNewHash(ctx);
|
||||
naHash_set(f->locals, ctx->argRef, args);
|
||||
} else {
|
||||
ERR(ctx, "function/method call invoked on uncallable object");
|
||||
}
|
||||
}
|
||||
|
||||
static naRef evalAndOr(struct Context* ctx, int op, naRef ra, naRef rb)
|
||||
{
|
||||
int a = boolify(ctx, ra);
|
||||
int b = boolify(ctx, rb);
|
||||
int result;
|
||||
if(op == OP_AND) result = a && b ? 1 : 0;
|
||||
else result = a || b ? 1 : 0;
|
||||
return naNum(result);
|
||||
}
|
||||
|
||||
static naRef evalEquality(int op, naRef ra, naRef rb)
|
||||
{
|
||||
int result = naEqual(ra, rb);
|
||||
return naNum((op==OP_EQ) ? result : !result);
|
||||
}
|
||||
|
||||
static naRef evalBinaryNumeric(struct Context* ctx, int op, naRef ra, naRef rb)
|
||||
{
|
||||
double a = numify(ctx, ra), b = numify(ctx, rb);
|
||||
switch(op) {
|
||||
case OP_PLUS: return naNum(a + b);
|
||||
case OP_MINUS: return naNum(a - b);
|
||||
case OP_MUL: return naNum(a * b);
|
||||
case OP_DIV: return naNum(a / b);
|
||||
case OP_LT: return naNum(a < b ? 1 : 0);
|
||||
case OP_LTE: return naNum(a <= b ? 1 : 0);
|
||||
case OP_GT: return naNum(a > b ? 1 : 0);
|
||||
case OP_GTE: return naNum(a >= b ? 1 : 0);
|
||||
}
|
||||
return naNil();
|
||||
}
|
||||
|
||||
// When a code object comes out of the constant pool and shows up on
|
||||
// the stack, it needs to be bound with the lexical context.
|
||||
static naRef bindFunction(struct Context* ctx, struct Frame* f, naRef code)
|
||||
{
|
||||
naRef next = f->func.ref.ptr.func->closure;
|
||||
naRef closure = naNewClosure(ctx, f->locals, next);
|
||||
naRef result = naNewFunc(ctx, code);
|
||||
result.ref.ptr.func->closure = closure;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int getClosure(struct naClosure* c, naRef sym, naRef* result)
|
||||
{
|
||||
while(c) {
|
||||
if(naHash_get(c->namespace, sym, result)) return 1;
|
||||
c = c->next.ref.ptr.closure;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get a local symbol, or check the closure list if it isn't there
|
||||
static naRef getLocal(struct Context* ctx, struct Frame* f, naRef sym)
|
||||
{
|
||||
naRef result;
|
||||
if(!naHash_get(f->locals, sym, &result)) {
|
||||
naRef c = f->func.ref.ptr.func->closure;
|
||||
if(!getClosure(c.ref.ptr.closure, sym, &result))
|
||||
ERR(ctx, "undefined symbol");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int setClosure(naRef closure, naRef sym, naRef val)
|
||||
{
|
||||
struct naClosure* c = closure.ref.ptr.closure;
|
||||
if(c == 0) { return 0; }
|
||||
else if(naHash_tryset(c->namespace, sym, val)) { return 1; }
|
||||
else { return setClosure(c->next, sym, val); }
|
||||
}
|
||||
|
||||
static naRef setLocal(struct Frame* f, naRef sym, naRef val)
|
||||
{
|
||||
// Try the locals first, if not already there try the closures in
|
||||
// order. Finally put it in the locals if nothing matched.
|
||||
if(!naHash_tryset(f->locals, sym, val))
|
||||
if(!setClosure(f->func.ref.ptr.func->closure, sym, val))
|
||||
naHash_set(f->locals, sym, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
// Recursively descend into the parents lists
|
||||
static int getMember(struct Context* ctx, naRef obj, naRef fld, naRef* result)
|
||||
{
|
||||
naRef p;
|
||||
if(!IS_HASH(obj)) ERR(ctx, "non-objects have no members");
|
||||
if(naHash_get(obj, fld, result)) {
|
||||
return 1;
|
||||
} else if(naHash_get(obj, ctx->parentsRef, &p)) {
|
||||
int i;
|
||||
if(!IS_VEC(p)) ERR(ctx, "parents field not vector");
|
||||
for(i=0; i<p.ref.ptr.vec->size; i++)
|
||||
if(getMember(ctx, p.ref.ptr.vec->array[i], fld, result))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PUSH(struct Context* ctx, naRef r)
|
||||
{
|
||||
if(ctx->opTop >= MAX_STACK_DEPTH) ERR(ctx, "stack overflow");
|
||||
ctx->opStack[ctx->opTop++] = r;
|
||||
}
|
||||
|
||||
static naRef POP(struct Context* ctx)
|
||||
{
|
||||
if(ctx->opTop == 0) ERR(ctx, "BUG: stack underflow");
|
||||
return ctx->opStack[--ctx->opTop];
|
||||
}
|
||||
|
||||
static naRef TOP(struct Context* ctx)
|
||||
{
|
||||
if(ctx->opTop == 0) ERR(ctx, "BUG: stack underflow");
|
||||
return ctx->opStack[ctx->opTop-1];
|
||||
}
|
||||
|
||||
static int ARG16(unsigned char* byteCode, struct Frame* f)
|
||||
{
|
||||
int arg = byteCode[f->ip]<<8 | byteCode[f->ip+1];
|
||||
f->ip += 2;
|
||||
return arg;
|
||||
}
|
||||
|
||||
// OP_EACH works like a vector get, except that it leaves the vector
|
||||
// and index on the stack, increments the index after use, and pops
|
||||
// the arguments and pushes a nil if the index is beyond the end.
|
||||
static void evalEach(struct Context* ctx)
|
||||
{
|
||||
int idx = (int)(ctx->opStack[ctx->opTop-1].num);
|
||||
naRef vec = ctx->opStack[ctx->opTop-2];
|
||||
if(idx >= vec.ref.ptr.vec->size) {
|
||||
ctx->opTop -= 2; // pop two values
|
||||
PUSH(ctx, naNil());
|
||||
return;
|
||||
}
|
||||
ctx->opStack[ctx->opTop-1].num = idx+1; // modify in place
|
||||
PUSH(ctx, naVec_get(vec, idx));
|
||||
}
|
||||
|
||||
static void run1(struct Context* ctx, struct Frame* f, naRef code)
|
||||
{
|
||||
naRef a, b, c;
|
||||
struct naCode* cd = code.ref.ptr.code;
|
||||
int op, arg;
|
||||
|
||||
if(f->ip >= cd->nBytes) {
|
||||
DBG(printf("Done with frame %d\n", ctx->fTop-1);)
|
||||
ctx->fTop--;
|
||||
if(ctx->fTop <= 0)
|
||||
ctx->done = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
op = cd->byteCode[f->ip++];
|
||||
DBG(printf("Stack Depth: %d\n", ctx->opTop));
|
||||
DBG(printOpDEBUG(f->ip-1, op));
|
||||
switch(op) {
|
||||
case OP_POP:
|
||||
POP(ctx);
|
||||
break;
|
||||
case OP_DUP:
|
||||
PUSH(ctx, ctx->opStack[ctx->opTop-1]);
|
||||
break;
|
||||
case OP_XCHG:
|
||||
a = POP(ctx); b = POP(ctx);
|
||||
PUSH(ctx, a); PUSH(ctx, b);
|
||||
break;
|
||||
case OP_PLUS: case OP_MUL: case OP_DIV: case OP_MINUS:
|
||||
case OP_LT: case OP_LTE: case OP_GT: case OP_GTE:
|
||||
a = POP(ctx); b = POP(ctx);
|
||||
PUSH(ctx, evalBinaryNumeric(ctx, op, b, a));
|
||||
break;
|
||||
case OP_EQ: case OP_NEQ:
|
||||
a = POP(ctx); b = POP(ctx);
|
||||
PUSH(ctx, evalEquality(op, b, a));
|
||||
break;
|
||||
case OP_AND: case OP_OR:
|
||||
a = POP(ctx); b = POP(ctx);
|
||||
PUSH(ctx, evalAndOr(ctx, op, a, b));
|
||||
break;
|
||||
case OP_CAT:
|
||||
// stringify can call the GC, so don't take stuff of the stack!
|
||||
if(ctx->opTop <= 1) ERR(ctx, "BUG: stack underflow");
|
||||
a = stringify(ctx, ctx->opStack[ctx->opTop-1]);
|
||||
b = stringify(ctx, ctx->opStack[ctx->opTop-2]);
|
||||
c = naStr_concat(naNewString(ctx), b, a);
|
||||
ctx->opTop -= 2;
|
||||
PUSH(ctx, c);
|
||||
break;
|
||||
case OP_NEG:
|
||||
a = POP(ctx);
|
||||
PUSH(ctx, naNum(-numify(ctx, a)));
|
||||
break;
|
||||
case OP_NOT:
|
||||
a = POP(ctx);
|
||||
PUSH(ctx, naNum(boolify(ctx, a) ? 0 : 1));
|
||||
break;
|
||||
case OP_PUSHCONST:
|
||||
a = cd->constants[ARG16(cd->byteCode, f)];
|
||||
if(IS_CODE(a)) a = bindFunction(ctx, f, a);
|
||||
PUSH(ctx, a);
|
||||
break;
|
||||
case OP_PUSHONE:
|
||||
PUSH(ctx, naNum(1));
|
||||
break;
|
||||
case OP_PUSHZERO:
|
||||
PUSH(ctx, naNum(0));
|
||||
break;
|
||||
case OP_PUSHNIL:
|
||||
PUSH(ctx, naNil());
|
||||
break;
|
||||
case OP_NEWVEC:
|
||||
PUSH(ctx, naNewVector(ctx));
|
||||
break;
|
||||
case OP_VAPPEND:
|
||||
b = POP(ctx); a = TOP(ctx);
|
||||
naVec_append(a, b);
|
||||
break;
|
||||
case OP_NEWHASH:
|
||||
PUSH(ctx, naNewHash(ctx));
|
||||
break;
|
||||
case OP_HAPPEND:
|
||||
c = POP(ctx); b = POP(ctx); a = TOP(ctx); // a,b,c: hash, key, val
|
||||
naHash_set(a, b, c);
|
||||
break;
|
||||
case OP_LOCAL:
|
||||
a = getLocal(ctx, f, POP(ctx));
|
||||
PUSH(ctx, a);
|
||||
break;
|
||||
case OP_SETLOCAL:
|
||||
a = POP(ctx); b = POP(ctx);
|
||||
PUSH(ctx, setLocal(f, b, a));
|
||||
break;
|
||||
case OP_MEMBER:
|
||||
a = POP(ctx); b = POP(ctx);
|
||||
if(!getMember(ctx, b, a, &c))
|
||||
ERR(ctx, "no such member");
|
||||
PUSH(ctx, c);
|
||||
break;
|
||||
case OP_SETMEMBER:
|
||||
c = POP(ctx); b = POP(ctx); a = POP(ctx); // a,b,c: hash, key, val
|
||||
if(!IS_HASH(a)) ERR(ctx, "non-objects have no members");
|
||||
naHash_set(a, b, c);
|
||||
PUSH(ctx, c);
|
||||
break;
|
||||
case OP_INSERT:
|
||||
c = POP(ctx); b = POP(ctx); a = POP(ctx); // a,b,c: box, key, val
|
||||
containerSet(ctx, a, b, c);
|
||||
PUSH(ctx, c);
|
||||
break;
|
||||
case OP_EXTRACT:
|
||||
b = POP(ctx); a = POP(ctx); // a,b: box, key
|
||||
PUSH(ctx, containerGet(ctx, a, b));
|
||||
break;
|
||||
case OP_JMP:
|
||||
f->ip = ARG16(cd->byteCode, f);
|
||||
DBG(printf(" [Jump to: %d]\n", f->ip);)
|
||||
break;
|
||||
case OP_JIFNIL:
|
||||
arg = ARG16(cd->byteCode, f);
|
||||
a = TOP(ctx);
|
||||
if(IS_NIL(a)) {
|
||||
POP(ctx); // Pops **ONLY** if it's nil!
|
||||
f->ip = arg;
|
||||
DBG(printf(" [Jump to: %d]\n", f->ip);)
|
||||
}
|
||||
break;
|
||||
case OP_JIFNOT:
|
||||
arg = ARG16(cd->byteCode, f);
|
||||
if(!boolify(ctx, POP(ctx))) {
|
||||
f->ip = arg;
|
||||
DBG(printf(" [Jump to: %d]\n", f->ip);)
|
||||
}
|
||||
break;
|
||||
case OP_FCALL:
|
||||
b = POP(ctx); a = POP(ctx); // a,b = func, args
|
||||
setupFuncall(ctx, a, b);
|
||||
break;
|
||||
case OP_MCALL:
|
||||
c = POP(ctx); b = POP(ctx); a = POP(ctx); // a,b,c = obj, func, args
|
||||
naVec_append(ctx->temps, a);
|
||||
setupFuncall(ctx, b, c);
|
||||
naHash_set(ctx->fStack[ctx->fTop-1].locals, ctx->meRef, a);
|
||||
break;
|
||||
case OP_RETURN:
|
||||
a = POP(ctx);
|
||||
ctx->opTop = f->bp; // restore the correct stack frame!
|
||||
ctx->fTop--;
|
||||
ctx->fStack[ctx->fTop].args.ref.ptr.vec->size = 0;
|
||||
PUSH(ctx, a);
|
||||
break;
|
||||
case OP_LINE:
|
||||
f->line = ARG16(cd->byteCode, f);
|
||||
break;
|
||||
case OP_EACH:
|
||||
evalEach(ctx);
|
||||
break;
|
||||
case OP_MARK: // save stack state (e.g. "setjmp")
|
||||
ctx->markStack[ctx->markTop++] = ctx->opTop;
|
||||
break;
|
||||
case OP_UNMARK: // pop stack state set by mark
|
||||
ctx->markTop--;
|
||||
break;
|
||||
case OP_BREAK: // restore stack state (FOLLOW WITH JMP!)
|
||||
ctx->opTop = ctx->markStack[--ctx->markTop];
|
||||
break;
|
||||
default:
|
||||
ERR(ctx, "BUG: bad opcode");
|
||||
}
|
||||
|
||||
if(ctx->fTop <= 0)
|
||||
ctx->done = 1;
|
||||
}
|
||||
|
||||
static void nativeCall(struct Context* ctx, struct Frame* f, naRef ccode)
|
||||
{
|
||||
naCFunction fptr = ccode.ref.ptr.ccode->fptr;
|
||||
naRef result = (*fptr)(ctx, f->args);
|
||||
ctx->fTop--;
|
||||
ctx->fStack[ctx->fTop].args.ref.ptr.vec->size = 0;
|
||||
PUSH(ctx, result);
|
||||
}
|
||||
|
||||
void naSave(struct Context* ctx, naRef obj)
|
||||
{
|
||||
ctx->save = obj;
|
||||
}
|
||||
|
||||
int naStackDepth(struct Context* ctx)
|
||||
{
|
||||
return ctx->fTop;
|
||||
}
|
||||
|
||||
int naGetLine(struct Context* ctx, int frame)
|
||||
{
|
||||
return ctx->fStack[ctx->fTop-1-frame].line;
|
||||
}
|
||||
|
||||
naRef naGetSourceFile(struct Context* ctx, int frame)
|
||||
{
|
||||
naRef f = ctx->fStack[ctx->fTop-1-frame].func;
|
||||
f = f.ref.ptr.func->code;
|
||||
return f.ref.ptr.code->srcFile;
|
||||
}
|
||||
|
||||
char* naGetError(struct Context* ctx)
|
||||
{
|
||||
return ctx->error;
|
||||
}
|
||||
|
||||
static naRef run(naContext ctx)
|
||||
{
|
||||
// Return early if an error occurred. It will be visible to the
|
||||
// caller via naGetError().
|
||||
ctx->error = 0;
|
||||
if(setjmp(ctx->jumpHandle))
|
||||
return naNil();
|
||||
|
||||
ctx->done = 0;
|
||||
while(!ctx->done) {
|
||||
struct Frame* f = &(ctx->fStack[ctx->fTop-1]);
|
||||
naRef code = f->func.ref.ptr.func->code;
|
||||
if(IS_CCODE(code)) nativeCall(ctx, f, code);
|
||||
else run1(ctx, f, code);
|
||||
|
||||
ctx->temps.ref.ptr.vec->size = 0; // Reset the temporaries
|
||||
DBG(printStackDEBUG(ctx);)
|
||||
}
|
||||
|
||||
DBG(printStackDEBUG(ctx);)
|
||||
return ctx->opStack[--ctx->opTop];
|
||||
}
|
||||
|
||||
naRef naBindFunction(naContext ctx, naRef code, naRef closure)
|
||||
{
|
||||
naRef func = naNewFunc(ctx, code);
|
||||
func.ref.ptr.func->closure = naNewClosure(ctx, closure, naNil());
|
||||
return func;
|
||||
}
|
||||
|
||||
naRef naCall(naContext ctx, naRef func, naRef args, naRef obj, naRef locals)
|
||||
{
|
||||
// We might have to allocate objects, which can call the GC. But
|
||||
// the call isn't on the Nasal stack yet, so the GC won't find our
|
||||
// C-space arguments.
|
||||
naVec_append(ctx->temps, func);
|
||||
naVec_append(ctx->temps, args);
|
||||
naVec_append(ctx->temps, obj);
|
||||
naVec_append(ctx->temps, locals);
|
||||
|
||||
if(IS_NIL(args))
|
||||
args = naNewVector(ctx);
|
||||
if(IS_NIL(locals))
|
||||
locals = naNewHash(ctx);
|
||||
if(!IS_FUNC(func)) {
|
||||
// Generate a noop closure for bare code objects
|
||||
naRef code = func;
|
||||
func = naNewFunc(ctx, code);
|
||||
func.ref.ptr.func->closure = naNewClosure(ctx, locals, naNil());
|
||||
}
|
||||
if(!IS_NIL(obj))
|
||||
naHash_set(locals, ctx->meRef, obj);
|
||||
|
||||
ctx->fTop = ctx->opTop = ctx->markTop = 0;
|
||||
setupFuncall(ctx, func, args);
|
||||
ctx->fStack[ctx->fTop-1].locals = locals;
|
||||
|
||||
return run(ctx);
|
||||
}
|
||||
|
||||
64
simgear/nasal/code.h
Normal file
64
simgear/nasal/code.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef _CODE_H
|
||||
#define _CODE_H
|
||||
|
||||
#include <setjmp.h>
|
||||
#include "nasal.h"
|
||||
#include "data.h"
|
||||
|
||||
#define MAX_STACK_DEPTH 1024
|
||||
#define MAX_RECURSION 128
|
||||
#define MAX_MARK_DEPTH 32
|
||||
|
||||
enum {
|
||||
OP_AND, OP_OR, OP_NOT, OP_MUL, OP_PLUS, OP_MINUS, OP_DIV, OP_NEG,
|
||||
OP_CAT, OP_LT, OP_LTE, OP_GT, OP_GTE, OP_EQ, OP_NEQ, OP_EACH,
|
||||
OP_JMP, OP_JIFNOT, OP_JIFNIL, OP_FCALL, OP_MCALL, OP_RETURN,
|
||||
OP_PUSHCONST, OP_PUSHONE, OP_PUSHZERO, OP_PUSHNIL, OP_POP,
|
||||
OP_DUP, OP_XCHG, OP_INSERT, OP_EXTRACT, OP_MEMBER, OP_SETMEMBER,
|
||||
OP_LOCAL, OP_SETLOCAL, OP_NEWVEC, OP_VAPPEND, OP_NEWHASH, OP_HAPPEND,
|
||||
OP_LINE, OP_MARK, OP_UNMARK, OP_BREAK
|
||||
};
|
||||
|
||||
struct Frame {
|
||||
naRef func; // naFunc object
|
||||
naRef locals; // local per-call namespace
|
||||
naRef args; // vector of arguments
|
||||
int ip; // instruction pointer into code
|
||||
int bp; // opStack pointer to start of frame
|
||||
int line; // current line number
|
||||
};
|
||||
|
||||
struct Context {
|
||||
// Garbage collecting allocators:
|
||||
struct naPool pools[NUM_NASAL_TYPES];
|
||||
|
||||
// Stack(s)
|
||||
struct Frame fStack[MAX_RECURSION];
|
||||
int fTop;
|
||||
naRef opStack[MAX_STACK_DEPTH];
|
||||
int opTop;
|
||||
int markStack[MAX_MARK_DEPTH];
|
||||
int markTop;
|
||||
int done;
|
||||
|
||||
// Constants
|
||||
naRef meRef;
|
||||
naRef argRef;
|
||||
naRef parentsRef;
|
||||
|
||||
// Error handling
|
||||
jmp_buf jumpHandle;
|
||||
char* error;
|
||||
|
||||
// GC-findable reference point for objects that may live on the
|
||||
// processor ("real") stack during execution. naNew() places them
|
||||
// here, and clears the array each time we return from a C
|
||||
// function.
|
||||
naRef temps;
|
||||
|
||||
naRef save;
|
||||
};
|
||||
|
||||
void printRefDEBUG(naRef r);
|
||||
|
||||
#endif // _CODE_H
|
||||
540
simgear/nasal/codegen.c
Normal file
540
simgear/nasal/codegen.c
Normal file
@@ -0,0 +1,540 @@
|
||||
#include "parse.h"
|
||||
#include "code.h"
|
||||
|
||||
// These are more sensical predicate names in most contexts in this file
|
||||
#define LEFT(tok) ((tok)->children)
|
||||
#define RIGHT(tok) ((tok)->lastChild)
|
||||
#define BINARY(tok) (LEFT(tok) && RIGHT(tok) && LEFT(tok) != RIGHT(tok))
|
||||
|
||||
// Forward references for recursion
|
||||
static void genExpr(struct Parser* p, struct Token* t);
|
||||
static void genExprList(struct Parser* p, struct Token* t);
|
||||
|
||||
static void emit(struct Parser* p, int byte)
|
||||
{
|
||||
if(p->cg->nBytes >= p->cg->codeAlloced) {
|
||||
int i, sz = p->cg->codeAlloced * 2;
|
||||
unsigned char* buf = naParseAlloc(p, sz);
|
||||
for(i=0; i<p->cg->codeAlloced; i++) buf[i] = p->cg->byteCode[i];
|
||||
p->cg->byteCode = buf;
|
||||
p->cg->codeAlloced = sz;
|
||||
}
|
||||
p->cg->byteCode[p->cg->nBytes++] = (unsigned char)byte;
|
||||
}
|
||||
|
||||
static void emitImmediate(struct Parser* p, int byte, int arg)
|
||||
{
|
||||
emit(p, byte);
|
||||
emit(p, arg >> 8);
|
||||
emit(p, arg & 0xff);
|
||||
}
|
||||
|
||||
static void genBinOp(int op, struct Parser* p, struct Token* t)
|
||||
{
|
||||
if(!LEFT(t) || !RIGHT(t))
|
||||
naParseError(p, "empty subexpression", t->line);
|
||||
genExpr(p, LEFT(t));
|
||||
genExpr(p, RIGHT(t));
|
||||
emit(p, op);
|
||||
}
|
||||
|
||||
static int newConstant(struct Parser* p, naRef c)
|
||||
{
|
||||
int i = p->cg->nConsts++;
|
||||
if(i > 0xffff) naParseError(p, "too many constants in code block", 0);
|
||||
naHash_set(p->cg->consts, naNum(i), c);
|
||||
return i;
|
||||
}
|
||||
|
||||
static naRef getConstant(struct Parser* p, int idx)
|
||||
{
|
||||
naRef c;
|
||||
naHash_get(p->cg->consts, naNum(idx), &c);
|
||||
return c;
|
||||
}
|
||||
|
||||
// Interns a scalar (!) constant and returns its index
|
||||
static int internConstant(struct Parser* p, naRef c)
|
||||
{
|
||||
naRef r;
|
||||
naHash_get(p->cg->interned, c, &r);
|
||||
if(!IS_NIL(r)) {
|
||||
return (int)r.num;
|
||||
} else {
|
||||
int idx = newConstant(p, c);
|
||||
naHash_set(p->cg->interned, c, naNum(idx));
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
static void genScalarConstant(struct Parser* p, struct Token* t)
|
||||
{
|
||||
naRef c = (t->str
|
||||
? naStr_fromdata(naNewString(p->context), t->str, t->strlen)
|
||||
: naNum(t->num));
|
||||
int idx = internConstant(p, c);
|
||||
emitImmediate(p, OP_PUSHCONST, idx);
|
||||
}
|
||||
|
||||
static int genLValue(struct Parser* p, struct Token* t)
|
||||
{
|
||||
if(t->type == TOK_LPAR) {
|
||||
return genLValue(p, LEFT(t)); // Handle stuff like "(a) = 1"
|
||||
} else if(t->type == TOK_SYMBOL) {
|
||||
genScalarConstant(p, t);
|
||||
return OP_SETLOCAL;
|
||||
} else if(t->type == TOK_DOT && RIGHT(t) && RIGHT(t)->type == TOK_SYMBOL) {
|
||||
genExpr(p, LEFT(t));
|
||||
genScalarConstant(p, RIGHT(t));
|
||||
return OP_SETMEMBER;
|
||||
} else if(t->type == TOK_LBRA) {
|
||||
genExpr(p, LEFT(t));
|
||||
genExpr(p, RIGHT(t));
|
||||
return OP_INSERT;
|
||||
} else {
|
||||
naParseError(p, "bad lvalue", t->line);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void genLambda(struct Parser* p, struct Token* t)
|
||||
{
|
||||
int idx;
|
||||
struct CodeGenerator* cgSave;
|
||||
naRef codeObj;
|
||||
if(LEFT(t)->type != TOK_LCURL)
|
||||
naParseError(p, "bad function definition", t->line);
|
||||
|
||||
// Save off the generator state while we do the new one
|
||||
cgSave = p->cg;
|
||||
codeObj = naCodeGen(p, LEFT(LEFT(t)));
|
||||
p->cg = cgSave;
|
||||
|
||||
idx = newConstant(p, codeObj);
|
||||
emitImmediate(p, OP_PUSHCONST, idx);
|
||||
}
|
||||
|
||||
static void genList(struct Parser* p, struct Token* t)
|
||||
{
|
||||
if(t->type == TOK_COMMA) {
|
||||
genExpr(p, LEFT(t));
|
||||
emit(p, OP_VAPPEND);
|
||||
genList(p, RIGHT(t));
|
||||
} else if(t->type == TOK_EMPTY) {
|
||||
return;
|
||||
} else {
|
||||
genExpr(p, t);
|
||||
emit(p, OP_VAPPEND);
|
||||
}
|
||||
}
|
||||
|
||||
static void genHashElem(struct Parser* p, struct Token* t)
|
||||
{
|
||||
if(t->type == TOK_EMPTY)
|
||||
return;
|
||||
if(t->type != TOK_COLON)
|
||||
naParseError(p, "bad hash/object initializer", t->line);
|
||||
if(LEFT(t)->type == TOK_SYMBOL) genScalarConstant(p, LEFT(t));
|
||||
else if(LEFT(t)->type == TOK_LITERAL) genExpr(p, LEFT(t));
|
||||
else naParseError(p, "bad hash/object initializer", t->line);
|
||||
genExpr(p, RIGHT(t));
|
||||
emit(p, OP_HAPPEND);
|
||||
}
|
||||
|
||||
static void genHash(struct Parser* p, struct Token* t)
|
||||
{
|
||||
if(t->type == TOK_COMMA) {
|
||||
genHashElem(p, LEFT(t));
|
||||
genHash(p, RIGHT(t));
|
||||
} else if(t->type != TOK_EMPTY) {
|
||||
genHashElem(p, t);
|
||||
}
|
||||
}
|
||||
|
||||
static void genFuncall(struct Parser* p, struct Token* t)
|
||||
{
|
||||
int op = OP_FCALL;
|
||||
if(LEFT(t)->type == TOK_DOT) {
|
||||
genExpr(p, LEFT(LEFT(t)));
|
||||
emit(p, OP_DUP);
|
||||
genScalarConstant(p, RIGHT(LEFT(t)));
|
||||
emit(p, OP_MEMBER);
|
||||
op = OP_MCALL;
|
||||
} else {
|
||||
genExpr(p, LEFT(t));
|
||||
}
|
||||
emit(p, OP_NEWVEC);
|
||||
if(RIGHT(t)) genList(p, RIGHT(t));
|
||||
emit(p, op);
|
||||
}
|
||||
|
||||
static void pushLoop(struct Parser* p, struct Token* label)
|
||||
{
|
||||
int i = p->cg->loopTop;
|
||||
p->cg->loops[i].breakIP = 0xffffff;
|
||||
p->cg->loops[i].contIP = 0xffffff;
|
||||
p->cg->loops[i].label = label;
|
||||
p->cg->loopTop++;
|
||||
emit(p, OP_MARK);
|
||||
}
|
||||
|
||||
static void popLoop(struct Parser* p)
|
||||
{
|
||||
p->cg->loopTop--;
|
||||
if(p->cg->loopTop < 0) naParseError(p, "BUG: loop stack underflow", -1);
|
||||
emit(p, OP_UNMARK);
|
||||
}
|
||||
|
||||
// Emit a jump operation, and return the location of the address in
|
||||
// the bytecode for future fixup in fixJumpTarget
|
||||
static int emitJump(struct Parser* p, int op)
|
||||
{
|
||||
int ip;
|
||||
emit(p, op);
|
||||
ip = p->cg->nBytes;
|
||||
emit(p, 0xff); // dummy address
|
||||
emit(p, 0xff);
|
||||
return ip;
|
||||
}
|
||||
|
||||
// Points a previous jump instruction at the current "end-of-bytecode"
|
||||
static void fixJumpTarget(struct Parser* p, int spot)
|
||||
{
|
||||
p->cg->byteCode[spot] = p->cg->nBytes >> 8;
|
||||
p->cg->byteCode[spot+1] = p->cg->nBytes & 0xff;
|
||||
}
|
||||
|
||||
static void genShortCircuit(struct Parser* p, struct Token* t)
|
||||
{
|
||||
int jumpNext, jumpEnd, isAnd = (t->type == TOK_AND);
|
||||
genExpr(p, LEFT(t));
|
||||
if(isAnd) emit(p, OP_NOT);
|
||||
jumpNext = emitJump(p, OP_JIFNOT);
|
||||
emit(p, isAnd ? OP_PUSHNIL : OP_PUSHONE);
|
||||
jumpEnd = emitJump(p, OP_JMP);
|
||||
fixJumpTarget(p, jumpNext);
|
||||
genExpr(p, RIGHT(t));
|
||||
fixJumpTarget(p, jumpEnd);
|
||||
}
|
||||
|
||||
|
||||
static void genIf(struct Parser* p, struct Token* tif, struct Token* telse)
|
||||
{
|
||||
int jumpNext, jumpEnd;
|
||||
genExpr(p, tif->children); // the test
|
||||
jumpNext = emitJump(p, OP_JIFNOT);
|
||||
genExprList(p, tif->children->next->children); // the body
|
||||
jumpEnd = emitJump(p, OP_JMP);
|
||||
fixJumpTarget(p, jumpNext);
|
||||
if(telse) {
|
||||
if(telse->type == TOK_ELSIF) genIf(p, telse, telse->next);
|
||||
else genExprList(p, telse->children->children);
|
||||
} else {
|
||||
emit(p, OP_PUSHNIL);
|
||||
}
|
||||
fixJumpTarget(p, jumpEnd);
|
||||
}
|
||||
|
||||
static void genIfElse(struct Parser* p, struct Token* t)
|
||||
{
|
||||
genIf(p, t, t->children->next->next);
|
||||
}
|
||||
|
||||
static int countSemis(struct Token* t)
|
||||
{
|
||||
if(!t || t->type != TOK_SEMI) return 0;
|
||||
return 1 + countSemis(RIGHT(t));
|
||||
}
|
||||
|
||||
static void genLoop(struct Parser* p, struct Token* body,
|
||||
struct Token* update, struct Token* label,
|
||||
int loopTop, int jumpEnd)
|
||||
{
|
||||
int cont, jumpOverContinue;
|
||||
|
||||
p->cg->loops[p->cg->loopTop-1].breakIP = jumpEnd-1;
|
||||
|
||||
jumpOverContinue = emitJump(p, OP_JMP);
|
||||
p->cg->loops[p->cg->loopTop-1].contIP = p->cg->nBytes;
|
||||
cont = emitJump(p, OP_JMP);
|
||||
fixJumpTarget(p, jumpOverContinue);
|
||||
|
||||
genExprList(p, body);
|
||||
emit(p, OP_POP);
|
||||
fixJumpTarget(p, cont);
|
||||
if(update) { genExpr(p, update); emit(p, OP_POP); }
|
||||
emitImmediate(p, OP_JMP, loopTop);
|
||||
fixJumpTarget(p, jumpEnd);
|
||||
popLoop(p);
|
||||
emit(p, OP_PUSHNIL); // Leave something on the stack
|
||||
}
|
||||
|
||||
static void genForWhile(struct Parser* p, struct Token* init,
|
||||
struct Token* test, struct Token* update,
|
||||
struct Token* body, struct Token* label)
|
||||
{
|
||||
int loopTop, jumpEnd;
|
||||
if(init) { genExpr(p, init); emit(p, OP_POP); }
|
||||
pushLoop(p, label);
|
||||
loopTop = p->cg->nBytes;
|
||||
genExpr(p, test);
|
||||
jumpEnd = emitJump(p, OP_JIFNOT);
|
||||
genLoop(p, body, update, label, loopTop, jumpEnd);
|
||||
}
|
||||
|
||||
static void genWhile(struct Parser* p, struct Token* t)
|
||||
{
|
||||
struct Token *test=LEFT(t)->children, *body, *label=0;
|
||||
int semis = countSemis(test);
|
||||
if(semis == 1) {
|
||||
label = LEFT(test);
|
||||
if(!label || label->type != TOK_SYMBOL)
|
||||
naParseError(p, "bad loop label", t->line);
|
||||
test = RIGHT(test);
|
||||
}
|
||||
else if(semis != 0)
|
||||
naParseError(p, "too many semicolons in while test", t->line);
|
||||
body = LEFT(RIGHT(t));
|
||||
genForWhile(p, 0, test, 0, body, label);
|
||||
}
|
||||
|
||||
static void genFor(struct Parser* p, struct Token* t)
|
||||
{
|
||||
struct Token *init, *test, *body, *update, *label=0;
|
||||
struct Token *h = LEFT(t)->children;
|
||||
int semis = countSemis(h);
|
||||
if(semis == 3) {
|
||||
if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
|
||||
naParseError(p, "bad loop label", h->line);
|
||||
label = LEFT(h);
|
||||
h=RIGHT(h);
|
||||
} else if(semis != 2) {
|
||||
naParseError(p, "wrong number of terms in for header", t->line);
|
||||
}
|
||||
|
||||
// Parse tree hell :)
|
||||
init = LEFT(h);
|
||||
test = LEFT(RIGHT(h));
|
||||
update = RIGHT(RIGHT(h));
|
||||
body = RIGHT(t)->children;
|
||||
genForWhile(p, init, test, update, body, label);
|
||||
}
|
||||
|
||||
static void genForEach(struct Parser* p, struct Token* t)
|
||||
{
|
||||
int loopTop, jumpEnd, assignOp;
|
||||
struct Token *elem, *body, *vec, *label=0;
|
||||
struct Token *h = LEFT(LEFT(t));
|
||||
int semis = countSemis(h);
|
||||
if(semis == 2) {
|
||||
if(!LEFT(h) || LEFT(h)->type != TOK_SYMBOL)
|
||||
naParseError(p, "bad loop label", h->line);
|
||||
label = LEFT(h);
|
||||
h = RIGHT(h);
|
||||
} else if (semis != 1) {
|
||||
naParseError(p, "wrong number of terms in foreach header", t->line);
|
||||
}
|
||||
elem = LEFT(h);
|
||||
vec = RIGHT(h);
|
||||
body = RIGHT(t)->children;
|
||||
|
||||
pushLoop(p, label);
|
||||
genExpr(p, vec);
|
||||
emit(p, OP_PUSHZERO);
|
||||
loopTop = p->cg->nBytes;
|
||||
emit(p, OP_EACH);
|
||||
jumpEnd = emitJump(p, OP_JIFNIL);
|
||||
assignOp = genLValue(p, elem);
|
||||
emit(p, OP_XCHG);
|
||||
emit(p, assignOp);
|
||||
emit(p, OP_POP);
|
||||
genLoop(p, body, 0, label, loopTop, jumpEnd);
|
||||
}
|
||||
|
||||
static int tokMatch(struct Token* a, struct Token* b)
|
||||
{
|
||||
int i, l = a->strlen;
|
||||
if(!a || !b) return 0;
|
||||
if(l != b->strlen) return 0;
|
||||
for(i=0; i<l; i++) if(a->str[i] != b->str[i]) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void genBreakContinue(struct Parser* p, struct Token* t)
|
||||
{
|
||||
int levels = 1, loop = -1, bp, cp, i;
|
||||
if(RIGHT(t)) {
|
||||
if(RIGHT(t)->type != TOK_SYMBOL)
|
||||
naParseError(p, "bad break/continue label", t->line);
|
||||
for(i=0; i<p->cg->loopTop; i++)
|
||||
if(tokMatch(RIGHT(t), p->cg->loops[i].label))
|
||||
loop = i;
|
||||
if(loop == -1)
|
||||
naParseError(p, "no match for break/continue label", t->line);
|
||||
levels = p->cg->loopTop - loop;
|
||||
}
|
||||
bp = p->cg->loops[p->cg->loopTop - levels].breakIP;
|
||||
cp = p->cg->loops[p->cg->loopTop - levels].contIP;
|
||||
for(i=0; i<levels; i++)
|
||||
emit(p, OP_BREAK);
|
||||
if(t->type == TOK_BREAK)
|
||||
emit(p, OP_PUSHNIL); // breakIP is always a JIFNOT/JIFNIL!
|
||||
emitImmediate(p, OP_JMP, t->type == TOK_BREAK ? bp : cp);
|
||||
}
|
||||
|
||||
static void genExpr(struct Parser* p, struct Token* t)
|
||||
{
|
||||
int i;
|
||||
if(t == 0)
|
||||
naParseError(p, "BUG: null subexpression", -1);
|
||||
if(t->line != p->cg->lastLine)
|
||||
emitImmediate(p, OP_LINE, t->line);
|
||||
p->cg->lastLine = t->line;
|
||||
switch(t->type) {
|
||||
case TOK_IF:
|
||||
genIfElse(p, t);
|
||||
break;
|
||||
case TOK_WHILE:
|
||||
genWhile(p, t);
|
||||
break;
|
||||
case TOK_FOR:
|
||||
genFor(p, t);
|
||||
break;
|
||||
case TOK_FOREACH:
|
||||
genForEach(p, t);
|
||||
break;
|
||||
case TOK_BREAK: case TOK_CONTINUE:
|
||||
genBreakContinue(p, t);
|
||||
break;
|
||||
case TOK_TOP:
|
||||
genExprList(p, LEFT(t));
|
||||
break;
|
||||
case TOK_FUNC:
|
||||
genLambda(p, t);
|
||||
break;
|
||||
case TOK_LPAR:
|
||||
if(BINARY(t) || !RIGHT(t)) genFuncall(p, t); // function invocation
|
||||
else genExpr(p, LEFT(t)); // simple parenthesis
|
||||
break;
|
||||
case TOK_LBRA:
|
||||
if(BINARY(t)) {
|
||||
genBinOp(OP_EXTRACT, p, t); // a[i]
|
||||
} else {
|
||||
emit(p, OP_NEWVEC);
|
||||
genList(p, LEFT(t));
|
||||
}
|
||||
break;
|
||||
case TOK_LCURL:
|
||||
emit(p, OP_NEWHASH);
|
||||
genHash(p, LEFT(t));
|
||||
break;
|
||||
case TOK_ASSIGN:
|
||||
i = genLValue(p, LEFT(t));
|
||||
genExpr(p, RIGHT(t));
|
||||
emit(p, i); // use the op appropriate to the lvalue
|
||||
break;
|
||||
case TOK_RETURN:
|
||||
if(RIGHT(t)) genExpr(p, RIGHT(t));
|
||||
else emit(p, OP_PUSHNIL);
|
||||
emit(p, OP_RETURN);
|
||||
break;
|
||||
case TOK_NOT:
|
||||
genExpr(p, RIGHT(t));
|
||||
emit(p, OP_NOT);
|
||||
break;
|
||||
case TOK_SYMBOL:
|
||||
genScalarConstant(p, t);
|
||||
emit(p, OP_LOCAL);
|
||||
break;
|
||||
case TOK_LITERAL:
|
||||
genScalarConstant(p, t);
|
||||
break;
|
||||
case TOK_MINUS:
|
||||
if(BINARY(t)) {
|
||||
genBinOp(OP_MINUS, p, t); // binary subtraction
|
||||
} else if(RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) {
|
||||
RIGHT(t)->num *= -1; // Pre-negate constants
|
||||
genScalarConstant(p, RIGHT(t));
|
||||
} else {
|
||||
genExpr(p, RIGHT(t)); // unary negation
|
||||
emit(p, OP_NEG);
|
||||
}
|
||||
break;
|
||||
case TOK_NEG:
|
||||
genExpr(p, RIGHT(t)); // unary negation (see also TOK_MINUS!)
|
||||
emit(p, OP_NEG);
|
||||
break;
|
||||
case TOK_DOT:
|
||||
genExpr(p, LEFT(t));
|
||||
if(RIGHT(t)->type != TOK_SYMBOL)
|
||||
naParseError(p, "object field not symbol", RIGHT(t)->line);
|
||||
genScalarConstant(p, RIGHT(t));
|
||||
emit(p, OP_MEMBER);
|
||||
break;
|
||||
case TOK_EMPTY: case TOK_NIL:
|
||||
emit(p, OP_PUSHNIL); break; // *NOT* a noop!
|
||||
case TOK_AND: case TOK_OR:
|
||||
genShortCircuit(p, t);
|
||||
break;
|
||||
case TOK_MUL: genBinOp(OP_MUL, p, t); break;
|
||||
case TOK_PLUS: genBinOp(OP_PLUS, p, t); break;
|
||||
case TOK_DIV: genBinOp(OP_DIV, p, t); break;
|
||||
case TOK_CAT: genBinOp(OP_CAT, p, t); break;
|
||||
case TOK_LT: genBinOp(OP_LT, p, t); break;
|
||||
case TOK_LTE: genBinOp(OP_LTE, p, t); break;
|
||||
case TOK_EQ: genBinOp(OP_EQ, p, t); break;
|
||||
case TOK_NEQ: genBinOp(OP_NEQ, p, t); break;
|
||||
case TOK_GT: genBinOp(OP_GT, p, t); break;
|
||||
case TOK_GTE: genBinOp(OP_GTE, p, t); break;
|
||||
default:
|
||||
naParseError(p, "parse error", t->line);
|
||||
};
|
||||
}
|
||||
|
||||
static void genExprList(struct Parser* p, struct Token* t)
|
||||
{
|
||||
if(t->type == TOK_SEMI) {
|
||||
genExpr(p, LEFT(t));
|
||||
if(RIGHT(t) && RIGHT(t)->type != TOK_EMPTY) {
|
||||
emit(p, OP_POP);
|
||||
genExprList(p, RIGHT(t));
|
||||
}
|
||||
} else {
|
||||
genExpr(p, t);
|
||||
}
|
||||
}
|
||||
|
||||
naRef naCodeGen(struct Parser* p, struct Token* t)
|
||||
{
|
||||
int i;
|
||||
naRef codeObj;
|
||||
struct naCode* code;
|
||||
struct CodeGenerator cg;
|
||||
|
||||
cg.lastLine = 0;
|
||||
cg.codeAlloced = 1024; // Start fairly big, this is a cheap allocation
|
||||
cg.byteCode = naParseAlloc(p, cg.codeAlloced);
|
||||
cg.nBytes = 0;
|
||||
cg.consts = naNewHash(p->context);
|
||||
cg.interned = naNewHash(p->context);
|
||||
cg.nConsts = 0;
|
||||
cg.loopTop = 0;
|
||||
p->cg = &cg;
|
||||
|
||||
genExprList(p, t);
|
||||
|
||||
// Now make a code object
|
||||
codeObj = naNewCode(p->context);
|
||||
code = codeObj.ref.ptr.code;
|
||||
code->nBytes = cg.nBytes;
|
||||
code->byteCode = naAlloc(cg.nBytes);
|
||||
for(i=0; i < cg.nBytes; i++)
|
||||
code->byteCode[i] = cg.byteCode[i];
|
||||
code->nConstants = cg.nConsts;
|
||||
code->constants = naAlloc(code->nConstants * sizeof(naRef));
|
||||
code->srcFile = p->srcFile;
|
||||
for(i=0; i<code->nConstants; i++)
|
||||
code->constants[i] = getConstant(p, i);
|
||||
|
||||
return codeObj;
|
||||
}
|
||||
142
simgear/nasal/data.h
Normal file
142
simgear/nasal/data.h
Normal file
@@ -0,0 +1,142 @@
|
||||
#ifndef _DATA_H
|
||||
#define _DATA_H
|
||||
|
||||
#include "nasal.h"
|
||||
|
||||
// Notes: A CODE object is a compiled set of bytecode instructions.
|
||||
// What actually gets executed at runtime is a bound FUNC object,
|
||||
// which combines the raw code with a pointer to a CLOSURE chain of
|
||||
// namespaces.
|
||||
enum { T_STR, T_VEC, T_HASH, T_CODE, T_CLOSURE, T_FUNC, T_CCODE, T_GHOST,
|
||||
NUM_NASAL_TYPES }; // V. important that this come last!
|
||||
|
||||
#define IS_REF(r) ((r).ref.reftag == NASAL_REFTAG)
|
||||
#define IS_NUM(r) ((r).ref.reftag != NASAL_REFTAG)
|
||||
#define IS_OBJ(r) (IS_REF((r)) && (r).ref.ptr.obj != 0)
|
||||
#define IS_NIL(r) (IS_REF((r)) && (r).ref.ptr.obj == 0)
|
||||
#define IS_STR(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_STR)
|
||||
#define IS_VEC(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_VEC)
|
||||
#define IS_HASH(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_HASH)
|
||||
#define IS_CODE(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_CODE)
|
||||
#define IS_FUNC(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_FUNC)
|
||||
#define IS_CLOSURE(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_CLOSURE)
|
||||
#define IS_CCODE(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_CCODE)
|
||||
#define IS_GHOST(r) (IS_OBJ((r)) && (r).ref.ptr.obj->type == T_GHOST)
|
||||
#define IS_CONTAINER(r) (IS_VEC(r)||IS_HASH(r))
|
||||
#define IS_SCALAR(r) (IS_NUM((r)) || IS_STR((r)))
|
||||
|
||||
// This is a macro instead of a separate struct to allow compilers to
|
||||
// avoid padding. GCC on x86, at least, will always padd the size of
|
||||
// an embedded struct up to 32 bits. Doing it this way allows the
|
||||
// implementing objects to pack in 16 bits worth of data "for free".
|
||||
#define GC_HEADER \
|
||||
unsigned char mark; \
|
||||
unsigned char type
|
||||
|
||||
struct naObj {
|
||||
GC_HEADER;
|
||||
};
|
||||
|
||||
struct naStr {
|
||||
GC_HEADER;
|
||||
int len;
|
||||
unsigned char* data;
|
||||
};
|
||||
|
||||
struct naVec {
|
||||
GC_HEADER;
|
||||
int size;
|
||||
int alloced;
|
||||
naRef* array;
|
||||
};
|
||||
|
||||
struct HashNode {
|
||||
naRef key;
|
||||
naRef val;
|
||||
struct HashNode* next;
|
||||
};
|
||||
|
||||
struct naHash {
|
||||
GC_HEADER;
|
||||
int size;
|
||||
int lgalloced;
|
||||
struct HashNode* nodes;
|
||||
struct HashNode** table;
|
||||
int nextnode;
|
||||
};
|
||||
|
||||
struct naCode {
|
||||
GC_HEADER;
|
||||
unsigned char* byteCode;
|
||||
int nBytes;
|
||||
naRef* constants;
|
||||
int nConstants;
|
||||
naRef srcFile;
|
||||
};
|
||||
|
||||
struct naFunc {
|
||||
GC_HEADER;
|
||||
naRef code;
|
||||
naRef closure;
|
||||
};
|
||||
|
||||
struct naClosure {
|
||||
GC_HEADER;
|
||||
naRef namespace;
|
||||
naRef next; // parent closure
|
||||
};
|
||||
|
||||
struct naCCode {
|
||||
GC_HEADER;
|
||||
naCFunction fptr;
|
||||
};
|
||||
|
||||
struct naGhost {
|
||||
GC_HEADER;
|
||||
naGhostType* gtype;
|
||||
void* ptr;
|
||||
};
|
||||
|
||||
struct naPool {
|
||||
int type;
|
||||
int elemsz;
|
||||
int nblocks;
|
||||
struct Block* blocks;
|
||||
int nfree; // number of entries in the free array
|
||||
int freesz; // size of the free array
|
||||
void** free; // pointers to usable elements
|
||||
};
|
||||
|
||||
void naFree(void* m);
|
||||
void* naAlloc(int n);
|
||||
void naBZero(void* m, int n);
|
||||
|
||||
int naTypeSize(int type);
|
||||
void naGarbageCollect();
|
||||
naRef naObj(int type, struct naObj* o);
|
||||
naRef naNew(naContext c, int type);
|
||||
naRef naNewCode(naContext c);
|
||||
naRef naNewClosure(naContext c, naRef namespace, naRef next);
|
||||
|
||||
int naStr_equal(naRef s1, naRef s2);
|
||||
naRef naStr_fromnum(naRef dest, double num);
|
||||
int naStr_numeric(naRef str);
|
||||
int naStr_parsenum(char* str, int len, double* result);
|
||||
int naStr_tonum(naRef str, double* out);
|
||||
|
||||
void naVec_init(naRef vec);
|
||||
|
||||
int naHash_tryset(naRef hash, naRef key, naRef val); // sets if exists
|
||||
void naHash_init(naRef hash);
|
||||
|
||||
void naGC_init(struct naPool* p, int type);
|
||||
struct naObj* naGC_get(struct naPool* p);
|
||||
int naGC_size(struct naPool* p);
|
||||
void naGC_mark(naRef r);
|
||||
void naGC_reap(struct naPool* p);
|
||||
|
||||
void naStr_gcclean(struct naStr* s);
|
||||
void naVec_gcclean(struct naVec* s);
|
||||
void naHash_gcclean(struct naHash* s);
|
||||
|
||||
#endif // _DATA_H
|
||||
211
simgear/nasal/debug.c
Normal file
211
simgear/nasal/debug.c
Normal file
@@ -0,0 +1,211 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nasal.h"
|
||||
#include "parse.h"
|
||||
#include "code.h"
|
||||
|
||||
// Bytecode operator to string
|
||||
char* opStringDEBUG(int op)
|
||||
{
|
||||
static char buf[256];
|
||||
switch(op) {
|
||||
case OP_AND: return "AND";
|
||||
case OP_OR: return "OR";
|
||||
case OP_NOT: return "NOT";
|
||||
case OP_MUL: return "MUL";
|
||||
case OP_PLUS: return "PLUS";
|
||||
case OP_MINUS: return "MINUS";
|
||||
case OP_DIV: return "DIV";
|
||||
case OP_NEG: return "NEG";
|
||||
case OP_CAT: return "CAT";
|
||||
case OP_LT: return "LT";
|
||||
case OP_LTE: return "LTE";
|
||||
case OP_GT: return "GT";
|
||||
case OP_GTE: return "GTE";
|
||||
case OP_EQ: return "EQ";
|
||||
case OP_NEQ: return "NEQ";
|
||||
case OP_EACH: return "EACH";
|
||||
case OP_JMP: return "JMP";
|
||||
case OP_JIFNOT: return "JIFNOT";
|
||||
case OP_JIFNIL: return "JIFNIL";
|
||||
case OP_FCALL: return "FCALL";
|
||||
case OP_MCALL: return "MCALL";
|
||||
case OP_RETURN: return "RETURN";
|
||||
case OP_PUSHCONST: return "PUSHCONST";
|
||||
case OP_PUSHONE: return "PUSHONE";
|
||||
case OP_PUSHZERO: return "PUSHZERO";
|
||||
case OP_PUSHNIL: return "PUSHNIL";
|
||||
case OP_POP: return "POP";
|
||||
case OP_DUP: return "DUP";
|
||||
case OP_XCHG: return "XCHG";
|
||||
case OP_INSERT: return "INSERT";
|
||||
case OP_EXTRACT: return "EXTRACT";
|
||||
case OP_MEMBER: return "MEMBER";
|
||||
case OP_SETMEMBER: return "SETMEMBER";
|
||||
case OP_LOCAL: return "LOCAL";
|
||||
case OP_SETLOCAL: return "SETLOCAL";
|
||||
case OP_NEWVEC: return "NEWVEC";
|
||||
case OP_VAPPEND: return "VAPPEND";
|
||||
case OP_NEWHASH: return "NEWHASH";
|
||||
case OP_HAPPEND: return "HAPPEND";
|
||||
case OP_LINE: return "LINE";
|
||||
case OP_MARK: return "MARK";
|
||||
case OP_UNMARK: return "UNMARK";
|
||||
case OP_BREAK: return "BREAK";
|
||||
}
|
||||
sprintf(buf, "<bad opcode: %d>\n", op);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Print a bytecode operator
|
||||
void printOpDEBUG(int ip, int op)
|
||||
{
|
||||
printf("IP: %d OP: %s\n", ip, opStringDEBUG(op));
|
||||
}
|
||||
|
||||
// Print a naRef
|
||||
void printRefDEBUG(naRef r)
|
||||
{
|
||||
int i;
|
||||
if(IS_NUM(r)) {
|
||||
printf("%f\n", r.num);
|
||||
} else if(IS_NIL(r)) {
|
||||
printf("<nil>\n");
|
||||
} else if(IS_STR(r)) {
|
||||
printf("\"");
|
||||
for(i=0; i<r.ref.ptr.str->len; i++)
|
||||
printf("%c", r.ref.ptr.str->data[i]);
|
||||
printf("\"\n");
|
||||
} else if(IS_VEC(r)) {
|
||||
printf("<vec>\n");
|
||||
} else if(IS_HASH(r)) {
|
||||
printf("<hash>\n");
|
||||
} else if(IS_FUNC(r)) {
|
||||
printf("<func>\n");
|
||||
} else if(IS_CLOSURE(r)) {
|
||||
printf("DEBUG: closure object on stack!\n");
|
||||
} else if(IS_CODE(r)) {
|
||||
printf("DEBUG: code object on stack!\n");
|
||||
} else printf("DEBUG ACK\n");
|
||||
}
|
||||
|
||||
// Print the operand stack of the specified context
|
||||
void printStackDEBUG(struct Context* ctx)
|
||||
{
|
||||
int i;
|
||||
printf("\n");
|
||||
for(i=ctx->opTop-1; i>=0; i--) {
|
||||
printf("] ");
|
||||
printRefDEBUG(ctx->opStack[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Token type to string
|
||||
char* tokString(int tok)
|
||||
{
|
||||
switch(tok) {
|
||||
case TOK_TOP: return "TOK_TOP";
|
||||
case TOK_AND: return "TOK_AND";
|
||||
case TOK_OR: return "TOK_OR";
|
||||
case TOK_NOT: return "TOK_NOT";
|
||||
case TOK_LPAR: return "TOK_LPAR";
|
||||
case TOK_RPAR: return "TOK_RPAR";
|
||||
case TOK_LBRA: return "TOK_LBRA";
|
||||
case TOK_RBRA: return "TOK_RBRA";
|
||||
case TOK_LCURL: return "TOK_LCURL";
|
||||
case TOK_RCURL: return "TOK_RCURL";
|
||||
case TOK_MUL: return "TOK_MUL";
|
||||
case TOK_PLUS: return "TOK_PLUS";
|
||||
case TOK_MINUS: return "TOK_MINUS";
|
||||
case TOK_NEG: return "TOK_NEG";
|
||||
case TOK_DIV: return "TOK_DIV";
|
||||
case TOK_CAT: return "TOK_CAT";
|
||||
case TOK_COLON: return "TOK_COLON";
|
||||
case TOK_DOT: return "TOK_DOT";
|
||||
case TOK_COMMA: return "TOK_COMMA";
|
||||
case TOK_SEMI: return "TOK_SEMI";
|
||||
case TOK_ASSIGN: return "TOK_ASSIGN";
|
||||
case TOK_LT: return "TOK_LT";
|
||||
case TOK_LTE: return "TOK_LTE";
|
||||
case TOK_EQ: return "TOK_EQ";
|
||||
case TOK_NEQ: return "TOK_NEQ";
|
||||
case TOK_GT: return "TOK_GT";
|
||||
case TOK_GTE: return "TOK_GTE";
|
||||
case TOK_IF: return "TOK_IF";
|
||||
case TOK_ELSIF: return "TOK_ELSIF";
|
||||
case TOK_ELSE: return "TOK_ELSE";
|
||||
case TOK_FOR: return "TOK_FOR";
|
||||
case TOK_FOREACH: return "TOK_FOREACH";
|
||||
case TOK_WHILE: return "TOK_WHILE";
|
||||
case TOK_RETURN: return "TOK_RETURN";
|
||||
case TOK_BREAK: return "TOK_BREAK";
|
||||
case TOK_CONTINUE: return "TOK_CONTINUE";
|
||||
case TOK_FUNC: return "TOK_FUNC";
|
||||
case TOK_SYMBOL: return "TOK_SYMBOL";
|
||||
case TOK_LITERAL: return "TOK_LITERAL";
|
||||
case TOK_EMPTY: return "TOK_EMPTY";
|
||||
case TOK_NIL: return "TOK_NIL";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Diagnostic: check all list pointers for sanity
|
||||
void ack()
|
||||
{
|
||||
printf("Bad token list!\n");
|
||||
exit(1);
|
||||
}
|
||||
void checkList(struct Token* start, struct Token* end)
|
||||
{
|
||||
struct Token* t = start;
|
||||
while(t) {
|
||||
if(t->next && t->next->prev != t) ack();
|
||||
if(t->next==0 && t != end) ack();
|
||||
t = t->next;
|
||||
}
|
||||
t = end;
|
||||
while(t) {
|
||||
if(t->prev && t->prev->next != t) ack();
|
||||
if(t->prev==0 && t != start) ack();
|
||||
t = t->prev;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Prints a single parser token to stdout
|
||||
void printToken(struct Token* t, char* prefix)
|
||||
{
|
||||
int i;
|
||||
printf("%sline %d %s ", prefix, t->line, tokString(t->type));
|
||||
if(t->type == TOK_LITERAL || t->type == TOK_SYMBOL) {
|
||||
if(t->str) {
|
||||
printf("\"");
|
||||
for(i=0; i<t->strlen; i++) printf("%c", t->str[i]);
|
||||
printf("\" (len: %d)", t->strlen);
|
||||
} else {
|
||||
printf("%f ", t->num);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Prints a parse tree to stdout
|
||||
void dumpTokenList(struct Token* t, int prefix)
|
||||
{
|
||||
char prefstr[128];
|
||||
int i;
|
||||
|
||||
prefstr[0] = 0;
|
||||
for(i=0; i<prefix; i++)
|
||||
strcat(prefstr, ". ");
|
||||
|
||||
while(t) {
|
||||
printToken(t, prefstr);
|
||||
dumpTokenList(t->children, prefix+1);
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
|
||||
223
simgear/nasal/gc.c
Normal file
223
simgear/nasal/gc.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include "nasal.h"
|
||||
#include "data.h"
|
||||
|
||||
#define MIN_BLOCK_SIZE 256
|
||||
|
||||
// "type" for an object freed by the collector
|
||||
#define T_GCFREED 123 // DEBUG
|
||||
|
||||
struct Block {
|
||||
int size;
|
||||
char* block;
|
||||
};
|
||||
|
||||
// Decremented every allocation. When it reaches zero, we do a
|
||||
// garbage collection. The value is reset to 1/2 of the total object
|
||||
// count each collection, which is sane: it ensures that no more than
|
||||
// 50% growth can happen between collections, and ensures that garbage
|
||||
// collection work is constant with allocation work (i.e. that O(N)
|
||||
// work is done only every O(1/2N) allocations).
|
||||
static int GlobalAllocCount = 256;
|
||||
|
||||
static void appendfree(struct naPool*p, struct naObj* o)
|
||||
{
|
||||
// Need more space?
|
||||
if(p->freesz <= p->nfree) {
|
||||
int i, n = 1+((3*p->nfree)>>1);
|
||||
void** newf = naAlloc(n * sizeof(void*));
|
||||
for(i=0; i<p->nfree; i++)
|
||||
newf[i] = p->free[i];
|
||||
naFree(p->free);
|
||||
p->free = newf;
|
||||
p->freesz = n;
|
||||
}
|
||||
|
||||
p->free[p->nfree++] = o;
|
||||
}
|
||||
|
||||
static void naCode_gcclean(struct naCode* o)
|
||||
{
|
||||
naFree(o->byteCode); o->byteCode = 0;
|
||||
naFree(o->constants); o->constants = 0;
|
||||
}
|
||||
|
||||
static void naGhost_gcclean(struct naGhost* g)
|
||||
{
|
||||
if(g->ptr) g->gtype->destroy(g->ptr);
|
||||
g->ptr = 0;
|
||||
}
|
||||
|
||||
static void freeelem(struct naPool* p, struct naObj* o)
|
||||
{
|
||||
// Mark the object as "freed" for debugging purposes
|
||||
o->type = T_GCFREED; // DEBUG
|
||||
|
||||
// Free any intrinsic (i.e. non-garbage collected) storage the
|
||||
// object might have
|
||||
switch(p->type) {
|
||||
case T_STR:
|
||||
naStr_gcclean((struct naStr*)o);
|
||||
break;
|
||||
case T_VEC:
|
||||
naVec_gcclean((struct naVec*)o);
|
||||
break;
|
||||
case T_HASH:
|
||||
naHash_gcclean((struct naHash*)o);
|
||||
break;
|
||||
case T_CODE:
|
||||
naCode_gcclean((struct naCode*)o);
|
||||
break;
|
||||
case T_GHOST:
|
||||
naGhost_gcclean((struct naGhost*)o);
|
||||
break;
|
||||
}
|
||||
|
||||
// And add it to the free list
|
||||
appendfree(p, o);
|
||||
}
|
||||
|
||||
static void newBlock(struct naPool* p, int need)
|
||||
{
|
||||
int i;
|
||||
char* buf;
|
||||
struct Block* newblocks;
|
||||
|
||||
if(need < MIN_BLOCK_SIZE)
|
||||
need = MIN_BLOCK_SIZE;
|
||||
|
||||
newblocks = naAlloc((p->nblocks+1) * sizeof(struct Block));
|
||||
for(i=0; i<p->nblocks; i++) newblocks[i] = p->blocks[i];
|
||||
naFree(p->blocks);
|
||||
p->blocks = newblocks;
|
||||
buf = naAlloc(need * p->elemsz);
|
||||
naBZero(buf, need * p->elemsz);
|
||||
p->blocks[p->nblocks].size = need;
|
||||
p->blocks[p->nblocks].block = buf;
|
||||
p->nblocks++;
|
||||
|
||||
for(i=0; i<need; i++) {
|
||||
struct naObj* o = (struct naObj*)(buf + i*p->elemsz);
|
||||
o->mark = 0;
|
||||
o->type = p->type;
|
||||
appendfree(p, o);
|
||||
}
|
||||
}
|
||||
|
||||
void naGC_init(struct naPool* p, int type)
|
||||
{
|
||||
p->type = type;
|
||||
p->elemsz = naTypeSize(type);
|
||||
p->nblocks = 0;
|
||||
p->blocks = 0;
|
||||
p->nfree = 0;
|
||||
p->freesz = 0;
|
||||
p->free = 0;
|
||||
naGC_reap(p);
|
||||
}
|
||||
|
||||
int naGC_size(struct naPool* p)
|
||||
{
|
||||
int i, total=0;
|
||||
for(i=0; i<p->nblocks; i++)
|
||||
total += ((struct Block*)(p->blocks + i))->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
struct naObj* naGC_get(struct naPool* p)
|
||||
{
|
||||
// Collect every GlobalAllocCount allocations.
|
||||
// This gets set to ~50% of the total object count each
|
||||
// collection (it's incremented in naGC_reap()).
|
||||
if(--GlobalAllocCount < 0) {
|
||||
GlobalAllocCount = 0;
|
||||
naGarbageCollect();
|
||||
}
|
||||
|
||||
// If we're out, then allocate an extra 12.5%
|
||||
if(p->nfree == 0)
|
||||
newBlock(p, naGC_size(p)/8);
|
||||
return p->free[--p->nfree];
|
||||
}
|
||||
|
||||
// Sets the reference bit on the object, and recursively on all
|
||||
// objects reachable from it. Clumsy: uses C stack recursion, which
|
||||
// is slower than it need be and may cause problems on some platforms
|
||||
// due to the very large stack depths that result.
|
||||
void naGC_mark(naRef r)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(IS_NUM(r) || IS_NIL(r))
|
||||
return;
|
||||
|
||||
if(r.ref.ptr.obj->mark == 1)
|
||||
return;
|
||||
|
||||
// Verify that the object hasn't been freed incorrectly:
|
||||
if(r.ref.ptr.obj->type == T_GCFREED) *(int*)0=0; // DEBUG
|
||||
|
||||
r.ref.ptr.obj->mark = 1;
|
||||
switch(r.ref.ptr.obj->type) {
|
||||
case T_VEC:
|
||||
for(i=0; i<r.ref.ptr.vec->size; i++)
|
||||
naGC_mark(r.ref.ptr.vec->array[i]);
|
||||
break;
|
||||
case T_HASH:
|
||||
if(r.ref.ptr.hash->table == 0)
|
||||
break;
|
||||
for(i=0; i < (1<<r.ref.ptr.hash->lgalloced); i++) {
|
||||
struct HashNode* hn = r.ref.ptr.hash->table[i];
|
||||
while(hn) {
|
||||
naGC_mark(hn->key);
|
||||
naGC_mark(hn->val);
|
||||
hn = hn->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_CODE:
|
||||
naGC_mark(r.ref.ptr.code->srcFile);
|
||||
for(i=0; i<r.ref.ptr.code->nConstants; i++)
|
||||
naGC_mark(r.ref.ptr.code->constants[i]);
|
||||
break;
|
||||
case T_CLOSURE:
|
||||
naGC_mark(r.ref.ptr.closure->namespace);
|
||||
naGC_mark(r.ref.ptr.closure->next);
|
||||
break;
|
||||
case T_FUNC:
|
||||
naGC_mark(r.ref.ptr.func->code);
|
||||
naGC_mark(r.ref.ptr.func->closure);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Collects all the unreachable objects into a free list, and
|
||||
// allocates more space if needed.
|
||||
void naGC_reap(struct naPool* p)
|
||||
{
|
||||
int i, elem, total = 0;
|
||||
p->nfree = 0;
|
||||
for(i=0; i<p->nblocks; i++) {
|
||||
struct Block* b = p->blocks + i;
|
||||
total += b->size;
|
||||
for(elem=0; elem < b->size; elem++) {
|
||||
struct naObj* o = (struct naObj*)(b->block + elem * p->elemsz);
|
||||
if(o->mark == 0)
|
||||
freeelem(p, o);
|
||||
o->mark = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Add 50% of our total to the global count
|
||||
GlobalAllocCount += total/2;
|
||||
|
||||
// Allocate more if necessary (try to keep 25-50% of the objects
|
||||
// available)
|
||||
if(p->nfree < total/4) {
|
||||
int used = total - p->nfree;
|
||||
int avail = total - used;
|
||||
int need = used/2 - avail;
|
||||
if(need > 0)
|
||||
newBlock(p, need);
|
||||
}
|
||||
}
|
||||
|
||||
223
simgear/nasal/hash.c
Normal file
223
simgear/nasal/hash.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include "nasal.h"
|
||||
#include "data.h"
|
||||
|
||||
static void realloc(naRef hash)
|
||||
{
|
||||
struct naHash* h = hash.ref.ptr.hash;
|
||||
int i, sz, oldsz = h->size;
|
||||
int oldcols = h->table ? 1 << h->lgalloced : 0;
|
||||
|
||||
// Keep a handle to our original objects
|
||||
struct HashNode* oldnodes = h->nodes;
|
||||
struct HashNode** oldtable = h->table;
|
||||
|
||||
// Figure out how big we need to be (start with a minimum size of
|
||||
// 16 entries)
|
||||
for(i=3; 1<<i < oldsz; i++);
|
||||
h->lgalloced = i+1;
|
||||
|
||||
// Allocate new ones (note that all the records are allocated in a
|
||||
// single chunk, to avoid zillions of tiny node allocations)
|
||||
sz = 1<<h->lgalloced;
|
||||
h->nodes = naAlloc(sz * (sizeof(struct HashNode) + sizeof(void*)));
|
||||
h->table = (struct HashNode**)(((char*)h->nodes) + sz*sizeof(struct HashNode));
|
||||
naBZero(h->table, sz * sizeof(void*));
|
||||
h->nextnode = 0;
|
||||
h->size = 0;
|
||||
|
||||
// Re-insert everything from scratch
|
||||
for(i=0; i<oldcols; i++) {
|
||||
struct HashNode* hn = oldtable[i];
|
||||
while(hn) {
|
||||
naHash_set(hash, hn->key, hn->val);
|
||||
hn = hn->next;
|
||||
}
|
||||
}
|
||||
|
||||
// Free the old memory
|
||||
naFree(oldnodes);
|
||||
}
|
||||
|
||||
// Computes a hash code for a given scalar
|
||||
static unsigned int hashcode(naRef r)
|
||||
{
|
||||
if(IS_NUM(r))
|
||||
{
|
||||
// Numbers get the number as a hash. Just use the bits and
|
||||
// xor them together. Note assumption that sizeof(double) >=
|
||||
// 2*sizeof(int).
|
||||
unsigned int* p = (unsigned int*)&(r.num);
|
||||
return p[0] ^ p[1];
|
||||
} else {
|
||||
// This is Daniel Bernstein's djb2 hash function that I found
|
||||
// on the web somewhere. It appears to work pretty well.
|
||||
unsigned int i, hash = 5831;
|
||||
for(i=0; i<r.ref.ptr.str->len; i++)
|
||||
hash = (hash * 33) ^ r.ref.ptr.str->data[i];
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
// Which column in a given hash does the key correspond to.
|
||||
static unsigned int hashcolumn(struct naHash* h, naRef key)
|
||||
{
|
||||
// Multiply by a big number, and take the top N bits. Note
|
||||
// assumption that sizeof(unsigned int) == 4.
|
||||
return (2654435769u * hashcode(key)) >> (32 - h->lgalloced);
|
||||
}
|
||||
|
||||
struct HashNode* find(struct naHash* h, naRef key)
|
||||
{
|
||||
struct HashNode* hn;
|
||||
if(h->table == 0)
|
||||
return 0;
|
||||
hn = h->table[hashcolumn(h, key)];
|
||||
while(hn) {
|
||||
if(naEqual(key, hn->key))
|
||||
return hn;
|
||||
hn = hn->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void naHash_init(naRef hash)
|
||||
{
|
||||
struct naHash* h = hash.ref.ptr.hash;
|
||||
h->size = 0;
|
||||
h->lgalloced = 0;
|
||||
h->table = 0;
|
||||
h->nodes = 0;
|
||||
}
|
||||
|
||||
// Make a temporary string on the stack
|
||||
static naRef tmpStr(struct naStr* str, char* key)
|
||||
{
|
||||
char* p = key;
|
||||
while(*p) { p++; }
|
||||
str->len = p - key;
|
||||
str->data = key;
|
||||
return naObj(T_STR, (struct naObj*)str);
|
||||
}
|
||||
|
||||
naRef naHash_cget(naRef hash, char* key)
|
||||
{
|
||||
struct naStr str;
|
||||
naRef result, key2 = tmpStr(&str, key);
|
||||
if(naHash_get(hash, key2, &result))
|
||||
return result;
|
||||
return naNil();
|
||||
}
|
||||
|
||||
void naHash_cset(naRef hash, char* key, naRef val)
|
||||
{
|
||||
struct naStr str;
|
||||
naRef key2 = tmpStr(&str, key);
|
||||
naHash_tryset(hash, key2, val);
|
||||
}
|
||||
|
||||
int naHash_get(naRef hash, naRef key, naRef* out)
|
||||
{
|
||||
struct naHash* h = hash.ref.ptr.hash;
|
||||
struct HashNode* n;
|
||||
if(!IS_HASH(hash)) return 0;
|
||||
n = find(h, key);
|
||||
if(n) {
|
||||
*out = n->val;
|
||||
return 1;
|
||||
} else {
|
||||
*out = naNil();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Simpler version. Don't create a new node if the value isn't there
|
||||
int naHash_tryset(naRef hash, naRef key, naRef val)
|
||||
{
|
||||
struct HashNode* n;
|
||||
if(!IS_HASH(hash)) return 0;
|
||||
n = find(hash.ref.ptr.hash, key);
|
||||
if(n) n->val = val;
|
||||
return n != 0;
|
||||
}
|
||||
|
||||
void naHash_set(naRef hash, naRef key, naRef val)
|
||||
{
|
||||
struct naHash* h = hash.ref.ptr.hash;
|
||||
unsigned int col;
|
||||
struct HashNode* n;
|
||||
|
||||
if(!IS_HASH(hash)) return;
|
||||
|
||||
n = find(h, key);
|
||||
if(n) {
|
||||
n->val = val;
|
||||
return;
|
||||
}
|
||||
|
||||
if(h->size+1 >= 1<<h->lgalloced)
|
||||
realloc(hash);
|
||||
|
||||
col = hashcolumn(h, key);
|
||||
n = h->nodes + h->nextnode++;
|
||||
n->key = key;
|
||||
n->val = val;
|
||||
n->next = h->table[col];
|
||||
h->table[col] = n;
|
||||
h->size++;
|
||||
}
|
||||
|
||||
// FIXME: this implementation does a realloc() after each delete, and
|
||||
// is therefore needlessly O(N). (The reason is that this avoids the
|
||||
// need to keep a free list around for the much more common case of
|
||||
// adding a new value. Modifying an existing value is O(1), of
|
||||
// course.)
|
||||
void naHash_delete(naRef hash, naRef key)
|
||||
{
|
||||
struct naHash* h = hash.ref.ptr.hash;
|
||||
int col;
|
||||
struct HashNode *last=0, *hn;
|
||||
if(!IS_HASH(hash)) return;
|
||||
col = hashcolumn(h, key);
|
||||
hn = h->table[col];
|
||||
while(hn) {
|
||||
if(naEqual(hn->key, key)) {
|
||||
if(last == 0) h->table[col] = hn->next;
|
||||
else last->next = hn->next;
|
||||
h->size--;
|
||||
realloc(hash);
|
||||
return;
|
||||
}
|
||||
last = hn;
|
||||
hn = hn->next;
|
||||
}
|
||||
}
|
||||
|
||||
void naHash_keys(naRef dst, naRef hash)
|
||||
{
|
||||
struct naHash* h = hash.ref.ptr.hash;
|
||||
int i;
|
||||
if(!IS_HASH(hash) || !h->table) return;
|
||||
for(i=0; i<(1<<h->lgalloced); i++) {
|
||||
struct HashNode* hn = h->table[i];
|
||||
while(hn) {
|
||||
naVec_append(dst, hn->key);
|
||||
hn = hn->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int naHash_size(naRef h)
|
||||
{
|
||||
if(!IS_HASH(h)) return 0;
|
||||
return h.ref.ptr.hash->size;
|
||||
}
|
||||
|
||||
void naHash_gcclean(struct naHash* h)
|
||||
{
|
||||
naFree(h->nodes);
|
||||
h->nodes = 0;
|
||||
h->size = 0;
|
||||
h->lgalloced = 0;
|
||||
h->table = 0;
|
||||
h->nextnode = 0;
|
||||
}
|
||||
333
simgear/nasal/lex.c
Normal file
333
simgear/nasal/lex.c
Normal file
@@ -0,0 +1,333 @@
|
||||
#include "parse.h"
|
||||
|
||||
// Static table of recognized lexemes in the language
|
||||
struct Lexeme {
|
||||
char* str;
|
||||
int tok;
|
||||
} LEXEMES[] = {
|
||||
{"and", TOK_AND},
|
||||
{"or", TOK_OR},
|
||||
{"!", TOK_NOT},
|
||||
{"(", TOK_LPAR},
|
||||
{")", TOK_RPAR},
|
||||
{"[", TOK_LBRA},
|
||||
{"]", TOK_RBRA},
|
||||
{"{", TOK_LCURL},
|
||||
{"}", TOK_RCURL},
|
||||
{"*", TOK_MUL},
|
||||
{"+", TOK_PLUS},
|
||||
{"-", TOK_MINUS},
|
||||
{"/", TOK_DIV},
|
||||
{"~", TOK_CAT},
|
||||
{":", TOK_COLON},
|
||||
{".", TOK_DOT},
|
||||
{",", TOK_COMMA},
|
||||
{";", TOK_SEMI},
|
||||
{"=", TOK_ASSIGN},
|
||||
{"<", TOK_LT},
|
||||
{"<=", TOK_LTE},
|
||||
{"==", TOK_EQ},
|
||||
{"!=", TOK_NEQ},
|
||||
{">", TOK_GT},
|
||||
{">=", TOK_GTE},
|
||||
{"nil", TOK_NIL},
|
||||
{"if", TOK_IF},
|
||||
{"elsif", TOK_ELSIF},
|
||||
{"else", TOK_ELSE},
|
||||
{"for", TOK_FOR},
|
||||
{"foreach", TOK_FOREACH},
|
||||
{"while", TOK_WHILE},
|
||||
{"return", TOK_RETURN},
|
||||
{"break", TOK_BREAK},
|
||||
{"continue", TOK_CONTINUE},
|
||||
{"func", TOK_FUNC}
|
||||
};
|
||||
|
||||
// Build a table of where each line ending is
|
||||
static int* findLines(struct Parser* p)
|
||||
{
|
||||
char* buf = p->buf;
|
||||
int sz = p->len/10 + 16;
|
||||
int* lines = naParseAlloc(p, (sizeof(int) * sz));
|
||||
int i, j, n=0;
|
||||
|
||||
for(i=0; i<p->len; i++) {
|
||||
// Not a line ending at all
|
||||
if(buf[i] != '\n' && buf[i] != '\r')
|
||||
continue;
|
||||
|
||||
// Skip over the \r of a \r\n pair.
|
||||
if(buf[i] == '\r' && (i+1)<p->len && buf[i+1] == '\n') {
|
||||
continue;
|
||||
}
|
||||
// Reallocate if necessary
|
||||
if(n == sz) {
|
||||
int* nl;
|
||||
sz *= 2;
|
||||
nl = naParseAlloc(p, sizeof(int) * sz);
|
||||
for(j=0; j<n; j++) nl[j] = lines[j];
|
||||
lines = nl;
|
||||
}
|
||||
lines[n++] = i;
|
||||
}
|
||||
p->lines = lines;
|
||||
p->nLines = n;
|
||||
return lines;
|
||||
}
|
||||
|
||||
// What line number is the index on?
|
||||
static int getLine(struct Parser* p, int index)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<p->nLines; i++)
|
||||
if(p->lines[i] > index)
|
||||
return (p->firstLine-1) + i+1;
|
||||
return (p->firstLine-1) + p->nLines+1;
|
||||
}
|
||||
|
||||
static void error(struct Parser* p, char* msg, int index)
|
||||
{
|
||||
naParseError(p, msg, getLine(p, index));
|
||||
}
|
||||
|
||||
// End index (the newline character) of the given line
|
||||
static int lineEnd(struct Parser* p, int line)
|
||||
{
|
||||
if(line > p->nLines) return p->len;
|
||||
return p->lines[line-1];
|
||||
}
|
||||
|
||||
static void newToken(struct Parser* p, int pos, int type,
|
||||
char* str, int slen, double num)
|
||||
{
|
||||
struct Token* tok;
|
||||
|
||||
tok = naParseAlloc(p, sizeof(struct Token));
|
||||
tok->type = type;
|
||||
tok->line = getLine(p, pos);
|
||||
tok->str = str;
|
||||
tok->strlen = slen;
|
||||
tok->num = num;
|
||||
tok->parent = &p->tree;
|
||||
tok->next = 0;
|
||||
tok->prev = p->tree.lastChild;
|
||||
tok->children = 0;
|
||||
tok->lastChild = 0;
|
||||
|
||||
// Context sensitivity hack: a "-" following a binary operator of
|
||||
// higher precedence (MUL and DIV, basically) must be a unary
|
||||
// negation. Needed to get precedence right in the parser for
|
||||
// expressiong like "a * -2"
|
||||
if(type == TOK_MINUS && tok->prev)
|
||||
if(tok->prev->type == TOK_MUL || tok->prev->type == TOK_DIV)
|
||||
tok->type = type = TOK_NEG;
|
||||
|
||||
if(!p->tree.children) p->tree.children = tok;
|
||||
if(p->tree.lastChild) p->tree.lastChild->next = tok;
|
||||
p->tree.lastChild = tok;
|
||||
}
|
||||
|
||||
// Parse a hex nibble
|
||||
static int hexc(char c, struct Parser* p, int index)
|
||||
{
|
||||
if(c >= '0' && c <= '9') return c - '0';
|
||||
if(c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
if(c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
error(p, "bad hex constant", index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Escape and returns a single backslashed expression in a single
|
||||
// quoted string. Trivial, just escape \' and leave everything else
|
||||
// alone.
|
||||
static void sqEscape(char* buf, int len, int index, struct Parser* p,
|
||||
char* cOut, int* eatenOut)
|
||||
{
|
||||
if(len < 2) error(p, "unterminated string", index);
|
||||
if(buf[1] == '\'') {
|
||||
*cOut = '\'';
|
||||
*eatenOut = 2;
|
||||
} else {
|
||||
*cOut = '\\';
|
||||
*eatenOut = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Ditto, but more complicated for double quotes.
|
||||
static void dqEscape(char* buf, int len, int index, struct Parser* p,
|
||||
char* cOut, int* eatenOut)
|
||||
{
|
||||
if(len < 2) error(p, "unterminated string", index);
|
||||
*eatenOut = 2;
|
||||
switch(buf[1]) {
|
||||
case '"': *cOut = '"'; break;
|
||||
case 'r': *cOut = '\r'; break;
|
||||
case 'n': *cOut = '\n'; break;
|
||||
case 't': *cOut = '\t'; break;
|
||||
case '\\': *cOut = '\\'; break;
|
||||
case 'x':
|
||||
if(len < 4) error(p, "unterminated string", index);
|
||||
*cOut = (char)((hexc(buf[2], p, index)<<4) | hexc(buf[3], p, index));
|
||||
*eatenOut = 4;
|
||||
break;
|
||||
default:
|
||||
// Unhandled, put the backslash back
|
||||
*cOut = '\\';
|
||||
*eatenOut = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Read in a string literal
|
||||
static int lexStringLiteral(struct Parser* p, int index, int singleQuote)
|
||||
{
|
||||
int i, j, len, iteration;
|
||||
char* out = 0;
|
||||
char* buf = p->buf;
|
||||
char endMark = singleQuote ? '\'' : '"';
|
||||
|
||||
for(iteration = 0; iteration<2; iteration++) {
|
||||
i = index+1;
|
||||
j = len = 0;
|
||||
while(i < p->len) {
|
||||
char c = buf[i];
|
||||
int eaten = 1;
|
||||
if(c == endMark)
|
||||
break;
|
||||
if(c == '\\') {
|
||||
if(singleQuote) sqEscape(buf+i, p->len-i, i, p, &c, &eaten);
|
||||
else dqEscape(buf+i, p->len-i, i, p, &c, &eaten);
|
||||
}
|
||||
if(iteration == 1) out[j++] = c;
|
||||
i += eaten;
|
||||
len++;
|
||||
}
|
||||
// Finished stage one -- allocate the buffer for stage two
|
||||
if(iteration == 0) out = naParseAlloc(p, len);
|
||||
}
|
||||
newToken(p, index, TOK_LITERAL, out, len, 0);
|
||||
return i+1;
|
||||
}
|
||||
|
||||
static int lexNumLiteral(struct Parser* p, int index)
|
||||
{
|
||||
int len = p->len, i = index;
|
||||
unsigned char* buf = p->buf;
|
||||
double d;
|
||||
|
||||
while(i<len && buf[i] >= '0' && buf[i] <= '9') i++;
|
||||
if(i<len && buf[i] == '.') {
|
||||
i++;
|
||||
while(i<len && buf[i] >= '0' && buf[i] <= '9') i++;
|
||||
}
|
||||
if(i<len && (buf[i] == 'e' || buf[i] == 'E')) {
|
||||
i++;
|
||||
if(i<len
|
||||
&& (buf[i] == '-' || buf[i] == '+')
|
||||
&& (i+1<len && buf[i+1] >= '0' && buf[i+1] <= '9')) i++;
|
||||
while(i<len && buf[i] >= '0' && buf[i] <= '9') i++;
|
||||
}
|
||||
naStr_parsenum(p->buf + index, i - index, &d);
|
||||
newToken(p, index, TOK_LITERAL, 0, 0, d);
|
||||
return i;
|
||||
}
|
||||
|
||||
static int trySymbol(struct Parser* p, int start)
|
||||
{
|
||||
int i = start;
|
||||
while((i < p->len) &&
|
||||
((p->buf[i] == '_') ||
|
||||
(p->buf[i] >= 'A' && p->buf[i] <= 'Z') ||
|
||||
(p->buf[i] >= 'a' && p->buf[i] <= 'z') ||
|
||||
(p->buf[i] >= '0' && p->buf[i] <= '9')))
|
||||
{ i++; }
|
||||
return i-start;
|
||||
}
|
||||
|
||||
// Returns the length of lexeme l if the buffer prefix matches, or
|
||||
// else zero.
|
||||
static int matchLexeme(char* buf, int len, char* l)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<len; i++) {
|
||||
if(l[i] == 0) return i;
|
||||
if(l[i] != buf[i]) return 0;
|
||||
}
|
||||
// Ran out of buffer. This is still OK if we're also at the end
|
||||
// of the lexeme.
|
||||
if(l[i] == 0) return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is dumb and algorithmically slow. It would be much more
|
||||
// elegant to sort and binary search the lexeme list, but that's a lot
|
||||
// more code and this really isn't very slow in practice; it checks
|
||||
// every byte of every lexeme for each input byte. There are less
|
||||
// than 100 bytes of lexemes in the grammar. Returns the number of
|
||||
// bytes in the lexeme read (or zero if none was recognized)
|
||||
static int tryLexemes(struct Parser* p, int index, int* lexemeOut)
|
||||
{
|
||||
int i, n, best, bestIndex=-1;
|
||||
char* start = p->buf + index;
|
||||
int len = p->len - index;
|
||||
|
||||
n = sizeof(LEXEMES) / sizeof(struct Lexeme);
|
||||
best = 0;
|
||||
for(i=0; i<n; i++) {
|
||||
int l = matchLexeme(start, len, LEXEMES[i].str);
|
||||
if(l > best) {
|
||||
best = l;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
if(best > 0) *lexemeOut = bestIndex;
|
||||
return best;
|
||||
}
|
||||
|
||||
void naLex(struct Parser* p)
|
||||
{
|
||||
int i = 0;
|
||||
findLines(p);
|
||||
while(i<p->len) {
|
||||
char c = p->buf[i];
|
||||
|
||||
// Whitespace, comments and string literals have obvious
|
||||
// markers and can be handled by a switch:
|
||||
int handled = 1;
|
||||
switch(c) {
|
||||
case ' ': case '\t': case '\n': case '\r': case '\f': case '\v':
|
||||
i++;
|
||||
break;
|
||||
case '#':
|
||||
i = lineEnd(p, getLine(p, i));
|
||||
break;
|
||||
case '\'': case '"':
|
||||
i = lexStringLiteral(p, i, (c=='"' ? 0 : 1));
|
||||
break;
|
||||
default:
|
||||
if(c >= '0' && c <= '9') i = lexNumLiteral(p, i);
|
||||
else handled = 0;
|
||||
}
|
||||
|
||||
// Lexemes and symbols are a little more complicated. Pick
|
||||
// the longest one that matches. Since some lexemes look like
|
||||
// symbols (e.g. "or") they need a higher precedence, but we
|
||||
// don't want a lexeme match to clobber the beginning of a
|
||||
// symbol (e.g. "orchid"). If neither match, we have a bad
|
||||
// character in the mix.
|
||||
if(!handled) {
|
||||
int symlen=0, lexlen=0, lexeme;
|
||||
lexlen = tryLexemes(p, i, &lexeme);
|
||||
if((c>='A' && c<='Z') || (c>='a' && c<='z') || (c=='_'))
|
||||
symlen = trySymbol(p, i);
|
||||
if(lexlen && lexlen >= symlen) {
|
||||
newToken(p, i, LEXEMES[lexeme].tok, 0, 0, 0);
|
||||
i += lexlen;
|
||||
} else if(symlen) {
|
||||
newToken(p, i, TOK_SYMBOL, p->buf+i, symlen, 0);
|
||||
i += symlen;
|
||||
} else {
|
||||
error(p, "illegal character", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
181
simgear/nasal/lib.c
Normal file
181
simgear/nasal/lib.c
Normal file
@@ -0,0 +1,181 @@
|
||||
#include "nasal.h"
|
||||
|
||||
// No need to include <string.h> just for this:
|
||||
// It needs a funny name because MSVC wants to treat "strlen" as a
|
||||
// special symbol. Ugh...
|
||||
static int StrLen(char* s)
|
||||
{
|
||||
char* s0 = s;
|
||||
while(*s) s++;
|
||||
return s - s0;
|
||||
}
|
||||
|
||||
static naRef size(naContext c, naRef args)
|
||||
{
|
||||
naRef r;
|
||||
if(naVec_size(args) == 0) return naNil();
|
||||
r = naVec_get(args, 0);
|
||||
if(naIsString(r)) return naNum(naStr_len(r));
|
||||
if(naIsVector(r)) return naNum(naVec_size(r));
|
||||
if(naIsHash(r)) return naNum(naHash_size(r));
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef keys(naContext c, naRef args)
|
||||
{
|
||||
naRef v, h = naVec_get(args, 0);
|
||||
if(!naIsHash(h)) return naNil();
|
||||
v = naNewVector(c);
|
||||
naHash_keys(v, h);
|
||||
return v;
|
||||
}
|
||||
|
||||
static naRef append(naContext c, naRef args)
|
||||
{
|
||||
naRef v = naVec_get(args, 0);
|
||||
naRef e = naVec_get(args, 1);
|
||||
if(!naIsVector(v)) return naNil();
|
||||
naVec_append(v, e);
|
||||
return v;
|
||||
}
|
||||
|
||||
static naRef pop(naContext c, naRef args)
|
||||
{
|
||||
naRef v = naVec_get(args, 0);
|
||||
if(!naIsVector(v)) return naNil();
|
||||
return naVec_removelast(v);
|
||||
}
|
||||
|
||||
static naRef setsize(naContext c, naRef args)
|
||||
{
|
||||
naRef v = naVec_get(args, 0);
|
||||
int sz = (int)naNumValue(naVec_get(args, 1)).num;
|
||||
if(!naIsVector(v)) return naNil();
|
||||
naVec_setsize(v, sz);
|
||||
return v;
|
||||
}
|
||||
|
||||
static naRef subvec(naContext c, naRef args)
|
||||
{
|
||||
int i;
|
||||
naRef nlen, result, v = naVec_get(args, 0);
|
||||
int len = 0, start = (int)naNumValue(naVec_get(args, 1)).num;
|
||||
nlen = naNumValue(naVec_get(args, 2));
|
||||
if(!naIsNil(nlen))
|
||||
len = (int)naNumValue(naVec_get(args, 2)).num;
|
||||
if(!naIsVector(v) || start < 0 || start >= naVec_size(v) || len < 0)
|
||||
return naNil();
|
||||
if(len == 0 || len > naVec_size(v) - start) len = naVec_size(v) - start;
|
||||
result = naNewVector(c);
|
||||
naVec_setsize(result, len);
|
||||
for(i=0; i<len; i++)
|
||||
naVec_set(result, i, naVec_get(v, start + i));
|
||||
return result;
|
||||
}
|
||||
|
||||
static naRef delete(naContext c, naRef args)
|
||||
{
|
||||
naRef h = naVec_get(args, 0);
|
||||
naRef k = naVec_get(args, 1);
|
||||
if(naIsHash(h)) naHash_delete(h, k);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef intf(naContext c, naRef args)
|
||||
{
|
||||
naRef n = naNumValue(naVec_get(args, 0));
|
||||
if(!naIsNil(n)) n.num = (int)n.num;
|
||||
return n;
|
||||
}
|
||||
|
||||
static naRef num(naContext c, naRef args)
|
||||
{
|
||||
return naNumValue(naVec_get(args, 0));
|
||||
}
|
||||
|
||||
static naRef streq(naContext c, naRef args)
|
||||
{
|
||||
int i;
|
||||
naRef a = naVec_get(args, 0);
|
||||
naRef b = naVec_get(args, 1);
|
||||
if(!naIsString(a) || !naIsString(b)) return naNil();
|
||||
if(naStr_len(a) != naStr_len(b)) return naNum(0);
|
||||
for(i=0; i<naStr_len(a); i++)
|
||||
if(naStr_data(a)[i] != naStr_data(b)[i])
|
||||
return naNum(0);
|
||||
return naNum(1);
|
||||
}
|
||||
|
||||
static naRef substr(naContext c, naRef args)
|
||||
{
|
||||
naRef src = naVec_get(args, 0);
|
||||
naRef startR = naVec_get(args, 1);
|
||||
naRef lenR = naVec_get(args, 2);
|
||||
int start, len;
|
||||
if(!naIsString(src)) return naNil();
|
||||
startR = naNumValue(startR);
|
||||
if(naIsNil(startR)) return naNil();
|
||||
start = (int)startR.num;
|
||||
if(naIsNil(lenR)) {
|
||||
len = naStr_len(src) - start;
|
||||
} else {
|
||||
lenR = naNumValue(lenR);
|
||||
if(naIsNil(lenR)) return naNil();
|
||||
len = (int)lenR.num;
|
||||
}
|
||||
return naStr_substr(naNewString(c), src, start, len);
|
||||
}
|
||||
|
||||
static naRef contains(naContext c, naRef args)
|
||||
{
|
||||
naRef hash = naVec_get(args, 0);
|
||||
naRef key = naVec_get(args, 1);
|
||||
if(naIsNil(hash) || naIsNil(key)) return naNil();
|
||||
if(!naIsHash(hash)) return naNil();
|
||||
return naHash_get(hash, key, &key) ? naNum(1) : naNum(0);
|
||||
}
|
||||
|
||||
static naRef typeOf(naContext c, naRef args)
|
||||
{
|
||||
naRef r = naVec_get(args, 0);
|
||||
char* t = "unknown";
|
||||
if(naIsNil(r)) t = "nil";
|
||||
else if(naIsNum(r)) t = "scalar";
|
||||
else if(naIsString(r)) t = "scalar";
|
||||
else if(naIsVector(r)) t = "vector";
|
||||
else if(naIsHash(r)) t = "hash";
|
||||
else if(naIsFunc(r)) t = "func";
|
||||
else if(naIsGhost(r)) t = "ghost";
|
||||
r = naStr_fromdata(naNewString(c), t, StrLen(t));
|
||||
return r;
|
||||
}
|
||||
|
||||
struct func { char* name; naCFunction func; };
|
||||
static struct func funcs[] = {
|
||||
{ "size", size },
|
||||
{ "keys", keys },
|
||||
{ "append", append },
|
||||
{ "pop", pop },
|
||||
{ "setsize", setsize },
|
||||
{ "subvec", subvec },
|
||||
{ "delete", delete },
|
||||
{ "int", intf },
|
||||
{ "num", num },
|
||||
{ "streq", streq },
|
||||
{ "substr", substr },
|
||||
{ "contains", contains },
|
||||
{ "typeof", typeOf },
|
||||
};
|
||||
|
||||
naRef naStdLib(naContext c)
|
||||
{
|
||||
naRef namespace = naNewHash(c);
|
||||
int i, n = sizeof(funcs)/sizeof(struct func);
|
||||
for(i=0; i<n; i++) {
|
||||
naRef code = naNewCCode(c, funcs[i].func);
|
||||
naRef name = naStr_fromdata(naNewString(c),
|
||||
funcs[i].name, StrLen(funcs[i].name));
|
||||
naHash_set(namespace, name, naNewFunc(c, code));
|
||||
}
|
||||
return namespace;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user