head	8.7;
access;
symbols;
locks; strict;
comment	@ * @;


8.7
date	2026.05.11.12.01.10;	author mcalabre;	state Exp;
branches;
next	8.6;

8.6
date	2026.03.29.13.53.56;	author mcalabre;	state Exp;
branches
	8.6.1.1;
next	8.5;

8.5
date	2025.12.06.13.47.41;	author mcalabre;	state Exp;
branches
	8.5.1.1;
next	8.4;

8.4
date	2024.10.28.13.56.16;	author mcalabre;	state Exp;
branches
	8.4.1.1;
next	8.3;

8.3
date	2024.05.13.16.33.00;	author mcalabre;	state Exp;
branches
	8.3.1.1;
next	8.2;

8.2
date	2023.11.16.10.00.29;	author mcalabre;	state Exp;
branches
	8.2.1.1;
next	8.1;

8.1
date	2023.07.05.17.12.07;	author mcalabre;	state Exp;
branches
	8.1.1.1;
next	8.0;

8.0
date	2023.07.01.06.15.04;	author mcalabre;	state Exp;
branches
	8.0.1.1;
next	7.13;

7.13
date	2022.10.07.03.43.35;	author mcalabre;	state Exp;
branches
	7.13.1.1;
next	7.12;

7.12
date	2022.09.09.04.57.58;	author mcalabre;	state Exp;
branches
	7.12.1.1;
next	7.11;

7.11
date	2022.04.26.06.13.52;	author mcalabre;	state Exp;
branches
	7.11.1.1;
next	7.10;

7.10
date	2022.04.23.14.25.15;	author mcalabre;	state Exp;
branches
	7.10.1.1;
next	7.9;

7.9
date	2022.03.25.15.14.48;	author mcalabre;	state Exp;
branches
	7.9.1.1;
next	7.8;

7.8
date	2022.03.25.06.11.49;	author mcalabre;	state Exp;
branches
	7.8.1.1;
next	7.7;

7.7
date	2021.07.12.06.36.49;	author mcalabre;	state Exp;
branches
	7.7.1.1;
next	7.6;

7.6
date	2021.04.13.12.57.01;	author mcalabre;	state Exp;
branches
	7.6.1.1;
next	7.5;

7.5
date	2021.03.20.05.54.58;	author mcalabre;	state Exp;
branches
	7.5.1.1;
next	7.4;

7.4
date	2021.01.31.02.24.51;	author mcalabre;	state Exp;
branches
	7.4.1.1;
next	7.3;

7.3
date	2020.06.03.03.37.02;	author mcalabre;	state Exp;
branches
	7.3.1.1;
next	7.2;

7.2
date	2020.03.09.07.31.23;	author mcalabre;	state Exp;
branches
	7.2.1.1;
next	7.1;

7.1
date	2019.12.31.13.25.19;	author mcalabre;	state Exp;
branches
	7.1.1.1;
next	6.4;

6.4
date	2019.08.15.09.30.18;	author mcalabre;	state Exp;
branches
	6.4.1.1;
next	6.3;

6.3
date	2019.07.12.07.33.39;	author mcalabre;	state Exp;
branches
	6.3.1.1;
next	6.2;

6.2
date	2018.10.20.10.03.13;	author mcalabre;	state Exp;
branches
	6.2.1.1;
next	6.1;

6.1
date	2018.10.19.08.35.17;	author mcalabre;	state Exp;
branches
	6.1.1.1;
next	5.20;

5.20
date	2018.10.05.05.32.41;	author mcalabre;	state Exp;
branches
	5.20.1.1;
next	5.19;

5.19
date	2018.07.26.15.37.04;	author mcalabre;	state Exp;
branches
	5.19.1.1;
next	5.18;

5.18
date	2018.01.10.08.32.14;	author mcalabre;	state Exp;
branches
	5.18.1.1;
next	5.17;

5.17
date	2017.09.18.08.44.23;	author mcalabre;	state Exp;
branches
	5.17.1.1;
next	5.16;

5.16
date	2017.01.15.04.25.01;	author mcalabre;	state Exp;
branches
	5.16.1.1;
next	5.15;

5.15
date	2016.04.05.12.55.10;	author mcalabre;	state Exp;
branches
	5.15.1.1;
next	5.14;

5.14
date	2016.02.07.10.49.31;	author mcalabre;	state Exp;
branches
	5.14.1.1;
next	5.13;

5.13
date	2016.01.26.08.51.13;	author mcalabre;	state Exp;
branches
	5.13.1.1;
next	5.12;

5.12
date	2015.11.15.02.13.00;	author mcalabre;	state Exp;
branches
	5.12.1.1;
next	5.11;

5.11
date	2015.10.18.09.13.05;	author mcalabre;	state Exp;
branches
	5.11.1.1;
next	5.10;

5.10
date	2015.10.09.08.19.15;	author mcalabre;	state Exp;
branches
	5.10.1.1;
next	5.9;

5.9
date	2015.07.21.09.20.01;	author mcalabre;	state Exp;
branches
	5.9.1.1;
next	5.8;

5.8
date	2015.07.08.11.03.59;	author mcalabre;	state Exp;
branches
	5.8.1.1;
next	5.7;

5.7
date	2015.06.29.02.44.16;	author mcalabre;	state Exp;
branches
	5.7.1.1;
next	5.6;

5.6
date	2015.06.14.07.11.24;	author mcalabre;	state Exp;
branches
	5.6.1.1;
next	5.5;

5.5
date	2015.05.05.13.16.31;	author mcalabre;	state Exp;
branches
	5.5.1.1;
next	5.4;

5.4
date	2015.04.21.14.41.05;	author mcalabre;	state Exp;
branches
	5.4.1.1;
next	5.3;

5.3
date	2015.04.21.02.50.51;	author mcalabre;	state Exp;
branches
	5.3.1.1;
next	5.2;

5.2
date	2015.04.15.12.35.07;	author mcalabre;	state Exp;
branches
	5.2.1.1;
next	5.1;

5.1
date	2015.04.07.10.56.36;	author mcalabre;	state Exp;
branches
	5.1.1.1;
next	5.0;

5.0
date	2015.04.05.12.24.59;	author mcalabre;	state Exp;
branches
	5.0.1.1;
next	4.25;

4.25
date	2014.12.14.14.29.36;	author mcalabre;	state Exp;
branches
	4.25.1.1;
next	4.24;

4.24
date	2014.09.18.15.25.00;	author mcalabre;	state Exp;
branches
	4.24.1.1;
next	4.23;

4.23
date	2014.05.13.05.50.51;	author mcalabre;	state Exp;
branches
	4.23.1.1;
next	4.22;

4.22
date	2014.04.12.15.03.52;	author mcalabre;	state Exp;
branches
	4.22.1.1;
next	4.21;

4.21
date	2014.03.24.05.12.27;	author mcalabre;	state Exp;
branches
	4.21.1.1;
next	4.20;

4.20
date	2013.12.18.05.42.49;	author mcalabre;	state Exp;
branches
	4.20.1.1;
next	4.19;

4.19
date	2013.09.29.14.17.51;	author mcalabre;	state Exp;
branches
	4.19.1.1;
next	4.18;

4.18
date	2013.07.13.10.00.04;	author mcalabre;	state Exp;
branches
	4.18.1.1;
next	4.17;

4.17
date	2013.01.29.05.29.20;	author cal103;	state Exp;
branches
	4.17.1.1;
next	4.16;

4.16
date	2012.11.07.04.42.44;	author cal103;	state Exp;
branches
	4.16.1.1;
next	4.15;

4.15
date	2012.09.26.14.26.05;	author cal103;	state Exp;
branches
	4.15.1.1;
next	4.14;

4.14
date	2012.07.13.10.02.27;	author cal103;	state Exp;
branches
	4.14.1.1;
next	4.13;

4.13
date	2012.03.14.07.39.30;	author cal103;	state Exp;
branches
	4.13.1.1;
next	4.12;

4.12
date	2012.02.29.07.57.56;	author cal103;	state Exp;
branches
	4.12.1.1;
next	4.11;

4.11
date	2012.02.20.23.30.02;	author cal103;	state Exp;
branches
	4.11.1.1;
next	4.10;

4.10
date	2012.02.05.23.41.44;	author cal103;	state Exp;
branches
	4.10.1.1;
next	4.9;

4.9
date	2012.01.24.05.40.29;	author cal103;	state Exp;
branches
	4.9.1.1;
next	4.8;

4.8
date	2011.08.15.08.05.53;	author cal103;	state Exp;
branches
	4.8.1.1;
next	4.7;

4.7
date	2011.02.07.07.03.42;	author cal103;	state Exp;
branches
	4.7.1.1;
next	4.6;

4.6
date	2010.11.16.06.15.31;	author cal103;	state Exp;
branches
	4.6.1.1;
next	4.5;

4.5
date	2010.07.16.07.01.25;	author cal103;	state Exp;
branches
	4.5.1.1;
next	4.4;

4.4
date	2009.08.06.07.41.33;	author cal103;	state Exp;
branches
	4.4.1.1;
next	4.3;

4.3
date	2007.12.27.05.41.36;	author cal103;	state Exp;
branches
	4.3.1.1;
next	4.2;

4.2
date	2005.09.22.09.10.53;	author cal103;	state Exp;
branches
	4.2.1.1;
next	4.1;

4.1
date	2005.08.25.12.39.53;	author cal103;	state Exp;
branches;
next	4.0;

4.0
date	2005.02.04.06.18.43;	author cal103;	state Exp;
branches;
next	3.6;

3.6
date	2004.08.25.04.45.50;	author cal103;	state Exp;
branches;
next	3.5;

3.5
date	2004.06.28.04.28.33;	author mcalabre;	state Exp;
branches;
next	0.0;

0.0
date	2004.06.28.04.27.28;	author mcalabre;	state Exp;
branches;
next	;

4.2.1.1
date	2005.12.05.02.39.43;	author cal103;	state Exp;
branches;
next	4.2.1.2;

4.2.1.2
date	2005.12.16.03.28.21;	author cal103;	state Exp;
branches;
next	4.2.1.3;

4.2.1.3
date	2007.06.26.04.42.00;	author cal103;	state Exp;
branches;
next	4.2.1.4;

4.2.1.4
date	2007.06.29.01.11.43;	author cal103;	state Exp;
branches;
next	4.2.1.5;

4.2.1.5
date	2007.07.12.00.28.04;	author cal103;	state Exp;
branches;
next	4.2.1.6;

4.2.1.6
date	2007.08.02.04.29.43;	author cal103;	state Exp;
branches;
next	4.2.1.7;

4.2.1.7
date	2007.08.02.04.40.35;	author cal103;	state Exp;
branches;
next	4.2.1.8;

4.2.1.8
date	2007.08.03.01.28.53;	author cal103;	state Exp;
branches;
next	4.2.1.9;

4.2.1.9
date	2007.08.03.05.17.55;	author cal103;	state Exp;
branches;
next	4.2.1.10;

4.2.1.10
date	2007.08.03.09.02.47;	author cal103;	state Exp;
branches;
next	4.2.1.11;

4.2.1.11
date	2007.12.03.07.21.00;	author cal103;	state Exp;
branches;
next	4.2.1.12;

4.2.1.12
date	2007.12.03.07.42.08;	author cal103;	state Exp;
branches;
next	4.2.1.13;

4.2.1.13
date	2007.12.03.07.50.12;	author cal103;	state Exp;
branches;
next	4.2.1.14;

4.2.1.14
date	2007.12.03.08.07.22;	author cal103;	state Exp;
branches;
next	4.2.1.15;

4.2.1.15
date	2007.12.03.08.16.53;	author cal103;	state Exp;
branches;
next	4.2.1.16;

4.2.1.16
date	2007.12.03.08.19.36;	author cal103;	state Exp;
branches;
next	4.2.1.17;

4.2.1.17
date	2007.12.22.07.29.53;	author cal103;	state Exp;
branches;
next	4.2.1.18;

4.2.1.18
date	2007.12.26.04.17.18;	author cal103;	state Exp;
branches;
next	4.2.1.19;

4.2.1.19
date	2007.12.27.05.06.52;	author cal103;	state Exp;
branches;
next	;

4.3.1.1
date	2007.12.27.13.23.47;	author cal103;	state Exp;
branches;
next	4.3.1.2;

4.3.1.2
date	2009.04.30.02.33.27;	author cal103;	state Exp;
branches;
next	4.3.1.3;

4.3.1.3
date	2009.07.22.04.52.32;	author cal103;	state Exp;
branches;
next	4.3.1.4;

4.3.1.4
date	2009.07.23.04.52.23;	author cal103;	state Exp;
branches;
next	;

4.4.1.1
date	2009.08.10.08.52.49;	author cal103;	state Exp;
branches;
next	4.4.1.2;

4.4.1.2
date	2010.01.19.03.42.50;	author cal103;	state Exp;
branches;
next	4.4.1.3;

4.4.1.3
date	2010.07.07.13.39.54;	author cal103;	state Exp;
branches;
next	;

4.5.1.1
date	2010.07.16.07.05.31;	author cal103;	state Exp;
branches;
next	;

4.6.1.1
date	2010.11.16.06.16.19;	author cal103;	state Exp;
branches;
next	4.6.1.2;

4.6.1.2
date	2010.11.24.01.22.53;	author cal103;	state Exp;
branches;
next	4.6.1.3;

4.6.1.3
date	2011.01.14.06.33.16;	author cal103;	state Exp;
branches;
next	;

4.7.1.1
date	2011.02.07.07.04.22;	author cal103;	state Exp;
branches;
next	;

4.8.1.1
date	2011.08.15.08.07.06;	author cal103;	state Exp;
branches;
next	4.8.1.2;

4.8.1.2
date	2012.01.24.05.23.06;	author cal103;	state Exp;
branches;
next	;

4.9.1.1
date	2012.01.24.05.41.45;	author cal103;	state Exp;
branches;
next	;

4.10.1.1
date	2012.02.05.23.42.46;	author cal103;	state Exp;
branches;
next	;

4.11.1.1
date	2012.02.20.23.31.13;	author cal103;	state Exp;
branches;
next	;

4.12.1.1
date	2012.02.29.07.59.10;	author cal103;	state Exp;
branches;
next	;

4.13.1.1
date	2012.03.14.07.40.37;	author cal103;	state Exp;
branches;
next	4.13.1.2;

4.13.1.2
date	2012.07.12.15.17.21;	author cal103;	state Exp;
branches;
next	4.13.1.3;

4.13.1.3
date	2012.07.13.03.34.20;	author cal103;	state Exp;
branches;
next	;

4.14.1.1
date	2012.07.13.10.04.44;	author cal103;	state Exp;
branches;
next	;

4.15.1.1
date	2012.09.26.14.27.51;	author cal103;	state Exp;
branches;
next	4.15.1.2;

4.15.1.2
date	2012.11.07.04.29.45;	author cal103;	state Exp;
branches;
next	;

4.16.1.1
date	2012.11.07.04.45.56;	author cal103;	state Exp;
branches;
next	4.16.1.2;

4.16.1.2
date	2013.01.29.03.42.59;	author cal103;	state Exp;
branches;
next	;

4.17.1.1
date	2013.01.29.05.32.32;	author cal103;	state Exp;
branches;
next	;

4.18.1.1
date	2013.07.13.10.02.37;	author mcalabre;	state Exp;
branches;
next	;

4.19.1.1
date	2013.09.29.14.20.38;	author mcalabre;	state Exp;
branches;
next	;

4.20.1.1
date	2013.12.18.05.46.55;	author mcalabre;	state Exp;
branches;
next	4.20.1.2;

4.20.1.2
date	2014.03.21.06.32.19;	author mcalabre;	state Exp;
branches;
next	;

4.21.1.1
date	2014.03.24.05.15.28;	author mcalabre;	state Exp;
branches;
next	;

4.22.1.1
date	2014.04.12.15.06.32;	author mcalabre;	state Exp;
branches;
next	;

4.23.1.1
date	2014.05.13.05.53.49;	author mcalabre;	state Exp;
branches;
next	;

4.24.1.1
date	2014.09.18.15.28.09;	author mcalabre;	state Exp;
branches;
next	;

4.25.1.1
date	2014.12.14.14.32.45;	author mcalabre;	state Exp;
branches;
next	4.25.1.2;

4.25.1.2
date	2015.01.06.01.01.06;	author mcalabre;	state Exp;
branches;
next	4.25.1.3;

4.25.1.3
date	2015.03.15.08.59.20;	author mcalabre;	state Exp;
branches;
next	4.25.1.4;

4.25.1.4
date	2015.04.03.01.53.15;	author mcalabre;	state Exp;
branches;
next	;

5.0.1.1
date	2015.04.05.12.28.00;	author mcalabre;	state Exp;
branches;
next	;

5.1.1.1
date	2015.04.07.11.01.10;	author mcalabre;	state Exp;
branches;
next	;

5.2.1.1
date	2015.04.15.12.39.14;	author mcalabre;	state Exp;
branches;
next	;

5.3.1.1
date	2015.04.21.02.54.02;	author mcalabre;	state Exp;
branches;
next	5.3.1.2;

5.3.1.2
date	2015.04.21.13.51.54;	author mcalabre;	state Exp;
branches;
next	;

5.4.1.1
date	2015.04.21.14.44.28;	author mcalabre;	state Exp;
branches;
next	5.4.1.2;

5.4.1.2
date	2015.05.02.15.53.28;	author mcalabre;	state Exp;
branches;
next	;

5.5.1.1
date	2015.05.05.13.21.00;	author mcalabre;	state Exp;
branches;
next	5.5.1.2;

5.5.1.2
date	2015.06.06.08.43.34;	author mcalabre;	state Exp;
branches;
next	;

5.6.1.1
date	2015.06.14.07.14.44;	author mcalabre;	state Exp;
branches;
next	5.6.1.2;

5.6.1.2
date	2015.06.21.04.54.23;	author mcalabre;	state Exp;
branches;
next	;

5.7.1.1
date	2015.06.29.02.47.24;	author mcalabre;	state Exp;
branches;
next	5.7.1.2;

5.7.1.2
date	2015.07.03.13.23.22;	author mcalabre;	state Exp;
branches;
next	5.7.1.3;

5.7.1.3
date	2015.07.05.08.06.59;	author mcalabre;	state Exp;
branches;
next	5.7.1.4;

5.7.1.4
date	2015.07.08.07.17.12;	author mcalabre;	state Exp;
branches;
next	;

5.8.1.1
date	2015.07.08.11.07.18;	author mcalabre;	state Exp;
branches;
next	;

5.9.1.1
date	2015.07.21.09.28.07;	author mcalabre;	state Exp;
branches;
next	5.9.1.2;

5.9.1.2
date	2015.08.23.08.27.12;	author mcalabre;	state Exp;
branches;
next	5.9.1.3;

5.9.1.3
date	2015.09.15.09.26.25;	author mcalabre;	state Exp;
branches;
next	5.9.1.4;

5.9.1.4
date	2015.10.09.07.03.52;	author mcalabre;	state Exp;
branches;
next	;

5.10.1.1
date	2015.10.09.08.22.35;	author mcalabre;	state Exp;
branches;
next	5.10.1.2;

5.10.1.2
date	2015.10.18.08.57.50;	author mcalabre;	state Exp;
branches;
next	;

5.11.1.1
date	2015.10.18.09.16.27;	author mcalabre;	state Exp;
branches;
next	;

5.12.1.1
date	2015.11.15.02.16.14;	author mcalabre;	state Exp;
branches;
next	5.12.1.2;

5.12.1.2
date	2016.01.25.05.17.04;	author mcalabre;	state Exp;
branches;
next	5.12.1.3;

5.12.1.3
date	2016.01.25.05.25.25;	author mcalabre;	state Exp;
branches;
next	;

5.13.1.1
date	2016.01.26.08.54.32;	author mcalabre;	state Exp;
branches;
next	;

5.14.1.1
date	2016.02.07.10.52.44;	author mcalabre;	state Exp;
branches;
next	;

5.15.1.1
date	2016.04.05.12.58.35;	author mcalabre;	state Exp;
branches;
next	5.15.1.2;

5.15.1.2
date	2017.01.15.04.14.00;	author mcalabre;	state Exp;
branches;
next	;

5.16.1.1
date	2017.01.15.04.28.59;	author mcalabre;	state Exp;
branches;
next	5.16.1.2;

5.16.1.2
date	2017.09.12.12.42.37;	author mcalabre;	state Exp;
branches;
next	5.16.1.3;

5.16.1.3
date	2017.09.12.14.20.01;	author mcalabre;	state Exp;
branches;
next	5.16.1.4;

5.16.1.4
date	2017.09.12.14.20.36;	author mcalabre;	state Exp;
branches;
next	;

5.17.1.1
date	2017.09.18.08.45.59;	author mcalabre;	state Exp;
branches;
next	5.17.1.2;

5.17.1.2
date	2017.12.05.01.38.46;	author mcalabre;	state Exp;
branches;
next	5.17.1.3;

5.17.1.3
date	2017.12.05.07.48.29;	author mcalabre;	state Exp;
branches;
next	5.17.1.4;

5.17.1.4
date	2017.12.05.21.22.25;	author mcalabre;	state Exp;
branches;
next	5.17.1.5;

5.17.1.5
date	2018.01.10.08.25.34;	author mcalabre;	state Exp;
branches;
next	;

5.18.1.1
date	2018.01.10.08.33.04;	author mcalabre;	state Exp;
branches;
next	5.18.1.2;

5.18.1.2
date	2018.07.24.14.03.44;	author mcalabre;	state Exp;
branches;
next	;

5.19.1.1
date	2018.07.26.15.41.40;	author mcalabre;	state Exp;
branches;
next	;

5.20.1.1
date	2018.10.05.05.33.33;	author mcalabre;	state Exp;
branches;
next	5.20.1.2;

5.20.1.2
date	2018.10.19.06.38.35;	author mcalabre;	state Exp;
branches;
next	;

6.1.1.1
date	2018.10.19.08.36.15;	author mcalabre;	state Exp;
branches;
next	;

6.2.1.1
date	2018.10.20.10.04.15;	author mcalabre;	state Exp;
branches;
next	6.2.1.2;

6.2.1.2
date	2019.05.10.01.56.50;	author mcalabre;	state Exp;
branches;
next	6.2.1.3;

6.2.1.3
date	2019.07.08.08.02.29;	author mcalabre;	state Exp;
branches;
next	;

6.3.1.1
date	2019.07.12.07.34.37;	author mcalabre;	state Exp;
branches;
next	;

6.4.1.1
date	2019.08.15.09.31.29;	author mcalabre;	state Exp;
branches;
next	6.4.1.2;

6.4.1.2
date	2019.12.16.03.22.01;	author mcalabre;	state Exp;
branches;
next	6.4.1.3;

6.4.1.3
date	2019.12.31.02.30.08;	author mcalabre;	state Exp;
branches;
next	6.4.1.4;

6.4.1.4
date	2019.12.31.03.28.03;	author mcalabre;	state Exp;
branches;
next	;

7.1.1.1
date	2019.12.31.13.28.19;	author mcalabre;	state Exp;
branches;
next	;

7.2.1.1
date	2020.03.09.07.34.50;	author mcalabre;	state Exp;
branches;
next	7.2.1.2;

7.2.1.2
date	2020.06.02.08.52.36;	author mcalabre;	state Exp;
branches;
next	;

7.3.1.1
date	2020.06.03.03.38.10;	author mcalabre;	state Exp;
branches;
next	7.3.1.2;

7.3.1.2
date	2020.08.17.11.19.09;	author mcalabre;	state Exp;
branches;
next	7.3.1.3;

7.3.1.3
date	2021.01.19.14.09.10;	author mcalabre;	state Exp;
branches;
next	7.3.1.4;

7.3.1.4
date	2021.01.28.12.29.30;	author mcalabre;	state Exp;
branches;
next	;

7.4.1.1
date	2021.01.31.02.26.24;	author mcalabre;	state Exp;
branches;
next	7.4.1.2;

7.4.1.2
date	2021.02.25.13.43.44;	author mcalabre;	state Exp;
branches;
next	7.4.1.3;

7.4.1.3
date	2021.02.25.14.17.41;	author mcalabre;	state Exp;
branches;
next	;

7.5.1.1
date	2021.03.20.05.56.42;	author mcalabre;	state Exp;
branches;
next	;

7.6.1.1
date	2021.04.13.13.00.35;	author mcalabre;	state Exp;
branches;
next	;

7.7.1.1
date	2021.07.12.06.38.27;	author mcalabre;	state Exp;
branches;
next	7.7.1.2;

7.7.1.2
date	2022.03.25.06.05.59;	author mcalabre;	state Exp;
branches;
next	;

7.8.1.1
date	2022.03.25.06.14.14;	author mcalabre;	state Exp;
branches;
next	;

7.9.1.1
date	2022.03.25.15.16.40;	author mcalabre;	state Exp;
branches;
next	;

7.10.1.1
date	2022.04.23.14.26.54;	author mcalabre;	state Exp;
branches;
next	;

7.11.1.1
date	2022.04.26.06.15.32;	author mcalabre;	state Exp;
branches;
next	;

7.12.1.1
date	2022.09.09.05.00.36;	author mcalabre;	state Exp;
branches;
next	;

7.13.1.1
date	2022.10.07.03.45.47;	author mcalabre;	state Exp;
branches;
next	7.13.1.2;

7.13.1.2
date	2023.06.03.08.24.14;	author mcalabre;	state Exp;
branches;
next	7.13.1.3;

7.13.1.3
date	2023.06.03.14.21.54;	author mcalabre;	state Exp;
branches;
next	7.13.1.4;

7.13.1.4
date	2023.06.15.03.58.10;	author mcalabre;	state Exp;
branches;
next	7.13.1.5;

7.13.1.5
date	2023.06.15.04.17.19;	author mcalabre;	state Exp;
branches;
next	;

8.0.1.1
date	2023.07.01.06.22.44;	author mcalabre;	state Exp;
branches;
next	;

8.1.1.1
date	2023.07.05.17.15.00;	author mcalabre;	state Exp;
branches;
next	;

8.2.1.1
date	2023.11.16.10.05.57;	author mcalabre;	state Exp;
branches;
next	8.2.1.2;

8.2.1.2
date	2023.12.20.13.13.25;	author mcalabre;	state Exp;
branches;
next	8.2.1.3;

8.2.1.3
date	2024.04.02.14.01.58;	author mcalabre;	state Exp;
branches;
next	;

8.3.1.1
date	2024.05.13.16.35.39;	author mcalabre;	state Exp;
branches;
next	;

8.4.1.1
date	2024.10.28.13.58.41;	author mcalabre;	state Exp;
branches;
next	8.4.1.2;

8.4.1.2
date	2025.12.06.10.29.54;	author mcalabre;	state Exp;
branches;
next	8.4.1.3;

8.4.1.3
date	2025.12.06.13.37.16;	author mcalabre;	state Exp;
branches;
next	;

8.5.1.1
date	2025.12.06.14.05.15;	author mcalabre;	state Exp;
branches;
next	8.5.1.2;

8.5.1.2
date	2026.03.29.13.36.16;	author mcalabre;	state Exp;
branches;
next	;

8.6.1.1
date	2026.03.29.14.19.26;	author mcalabre;	state Exp;
branches;
next	8.6.1.2;

8.6.1.2
date	2026.04.10.03.48.25;	author mcalabre;	state Exp;
branches;
next	;


desc
@Flex description file containing a lexical scanner definition for extracting
the WCS cards from a FITS primary image or image extension header.
@


8.7
log
@WCSLIB 8.7
@
text
@/*============================================================================
  WCSLIB 8.7 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2026, Mark Calabretta

  This file is part of WCSLIB.

  WCSLIB is free software: you can redistribute it and/or modify it under the
  terms of the GNU Lesser General Public License as published by the Free
  Software Foundation, either version 3 of the License, or (at your option)
  any later version.

  WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
  more details.

  You should have received a copy of the GNU Lesser General Public License
  along with WCSLIB.  If not, see http://www.gnu.org/licenses.

  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
  http://www.atnf.csiro.au/computing/software/wcs
  $Id: wcspih.l,v 8.6.1.2 2026/04/10 03:48:25 mcalabre Exp mcalabre $
*=============================================================================
*
* wcspih.l is a Flex description file containing the definition of a lexical
* scanner for parsing the WCS keyrecords from a FITS primary image or image
* extension header.
*
* wcspih.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
* of the user interface and operating notes.
*
* Implementation notes
* --------------------
* Use of the WCSAXESa keyword is not mandatory.  Its default value is "the
* larger of NAXIS and the largest index of these keywords [i.e. CRPIXj, PCi_j
* or CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS header".
* Consequently the definition of WCSAXESa effectively invalidates the use of
* NAXIS for determining the number of coordinate axes and forces a preliminary
* pass through the header to determine the "largest index" in headers where
* WCSAXESa was omitted.
*
* Furthermore, since the use of WCSAXESa is optional, there is no way to
* determine the number of coordinate representations (the "a" value) other
* than by parsing all of the WCS keywords in the header; even if WCSAXESa was
* specified for some representations it cannot be known in advance whether it
* was specified for all of those present in the header.
*
* Hence the definition of WCSAXESa forces the scanner to be implemented in two
* passes.  The first pass is used to determine the number of coordinate
* representations (up to 27) and the number of coordinate axes in each.
* Effectively WCSAXESa is ignored unless it exceeds the "largest index" in
* which case the keywords for the extra axes assume their default values.  The
* number of PVi_ma and PSi_ma keywords in each representation is also counted
* in the first pass.
*
* On completion of the first pass, memory is allocated for an array of the
* required number of wcsprm structs and each of these is initialized
* appropriately.  These structs are filled in the second pass.
*
* The parser does not check for duplicated keywords, it accepts the last
* encountered.
*
*===========================================================================*/

/* Options. */
%option full
%option never-interactive
%option noinput
%option noyywrap
%option outfile="wcspih.c"
%option prefix="wcspih"
%option reentrant
%option extra-type="struct wcspih_extra *"

/* Indices for parameterized keywords. */
Z1	[0-9]
Z2	[0-9]{2}
Z3	[0-9]{3}
Z4	[0-9]{4}
Z5	[0-9]{5}
Z6	[0-9]{6}

I1	[1-9]
I2	[1-9][0-9]
I3	[1-9][0-9]{2}
I4	[1-9][0-9]{3}

/* Alternate coordinate system identifier. */
ALT	[ A-Z]

/* Keyvalue data types. */
INTEGER	[+-]?[0-9]+
FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eEdD][+-]?[0-9]+)?
STRING	'([^']|'')*'
RECORD	'[^']*'
FIELD	[a-zA-Z_][a-zA-Z_0-9.]*

/* Inline comment syntax. */
INLINE " "*(\/.*)?

/* Exclusive start states. */
%x CCia CCi_ja CCCCCia CCi_ma CCCCCCCa CCCCCCCC
%x CROTAi PROJPn SIP2 SIP3 DSSAMDXY PLTDECSN
%x VALUE INTEGER_VAL FLOAT_VAL FLOAT2_VAL STRING_VAL
%x RECORD_VAL RECFIELD RECCOLON RECVALUE RECEND
%x COMMENT
%x DISCARD ERROR FLUSH

%{
#include <math.h>
#include <setjmp.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "wcsmath.h"
#include "wcsprintf.h"
#include "wcsutil.h"

#include "dis.h"
#include "wcs.h"
#include "wcshdr.h"

#define INTEGER 0
#define FLOAT   1
#define FLOAT2  2
#define STRING  3
#define RECORD  4

#define PRIOR   1
#define SEQUENT 2

#define SIP     1
#define DSS     2
#define WAT     3

// User data associated with yyscanner.
struct wcspih_extra {
  // Values passed to YY_INPUT.
  char *hdr;
  int  nkeyrec;

  // Used in preempting the call to exit() by yy_fatal_error().
  jmp_buf abort_jmp_env;
};

#define YY_DECL int wcspih_scanner(char *header, int nkeyrec, int relax, \
 int ctrl, int *nreject, int *nwcs, struct wcsprm **wcs, yyscan_t yyscanner)

#define YY_INPUT(inbuff, count, bufsize) \
	{ \
	  if (yyextra->nkeyrec) { \
	    strncpy(inbuff, yyextra->hdr, 80); \
	    inbuff[80] = '\n'; \
	    yyextra->hdr += 80; \
	    yyextra->nkeyrec--; \
	    count = 81; \
	  } else { \
	    count = YY_NULL; \
	  } \
	}

// Preempt the call to exit() by yy_fatal_error().
#define exit(status) longjmp(yyextra->abort_jmp_env, status);

// Internal helper functions.
static YY_DECL;
static int wcspih_final(int ndp[], int ndq[], int distran, double dsstmp[],
             char *wat[], int *nwcs, struct wcsprm **wcs);
static int wcspih_init1(int naxis, int alts[], int dpq[], int npv[],
             int nps[], int ndp[], int ndq[], int auxprm, int distran,
             int *nwcs, struct wcsprm **wcs);
static void wcspih_pass1(int naxis, int i, int j, char a, int distype,
             int alts[], int dpq[], int *npptr);

static int wcspih_jdref(double *wptr,   const double *jdref);
static int wcspih_jdrefi(double *wptr,  const double *jdrefi);
static int wcspih_jdreff(double *wptr,  const double *jdreff);
static int wcspih_epoch(double *wptr,   const double *epoch);
static int wcspih_vsource(double *wptr, const double *vsource);

static int wcspih_timepixr(double timepixr);

%}

%%
	int  p, q;
	char *errmsg, errtxt[80], *keyname, strtmp[80], *wat[2], *watstr;
	int  alts[27], dpq[27], inttmp, ndp[27], ndq[27], nps[27], npv[27],
	     rectype;
	double dbltmp, dbl2tmp[2], dsstmp[20];
	struct auxprm auxtem;
	struct disprm distem;
	struct wcsprm wcstem;
	
	int naxis = 0;
	for (int ialt = 0; ialt < 27; ialt++) {
	  alts[ialt] = 0;
	  dpq[ialt]  = 0;
	  npv[ialt]  = 0;
	  nps[ialt]  = 0;
	  ndp[ialt]  = 0;
	  ndq[ialt]  = 0;
	}
	
	// Our handle on the input stream.
	char *keyrec = header;
	char *hptr = header;
	char *keep = 0x0;
	
	// For keeping tallies of keywords found.
	*nreject = 0;
	int nvalid = 0;
	int nother = 0;
	
	// If strict, then also reject.
	if (relax & WCSHDR_strict) relax |= WCSHDR_reject;
	
	// Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma.
	int i = 0;
	int j = 0;
	int m = 0;
	char a = ' ';
	
	// For decoding the keyvalue.
	int valtype = -1;
	int distype =  0;
	void *vptr  = 0x0;
	
	// For keywords that require special handling.
	int altlin  = 0;
	int *npptr  = 0x0;
	int (*chekval)(double) = 0x0;
	int (*special)(double *, const double *) = 0x0;
	int auxprm  = 0;
	int naux    = 0;
	int distran = 0;
	int sipflag = 0;
	int dssflag = 0;
	int watflag = 0;
	int watn    = 0;
	
	// The data structures produced.
	*nwcs = 0;
	*wcs  = 0x0;
	
	// Control variables.
	int ipass = 1;
	int npass = 2;
	
	// User data associated with yyscanner.
	yyextra->hdr = header;
	yyextra->nkeyrec = nkeyrec;
	
	// Return here via longjmp() invoked by yy_fatal_error().
	if (setjmp(yyextra->abort_jmp_env)) {
	  return WCSHDRERR_PARSER;
	}
	
	BEGIN(INITIAL);


^NAXIS"   = "" "*{INTEGER}{INLINE} {
	  keyname = "NAXISn";
	
	  if (ipass == 1) {
	    sscanf(yytext, "NAXIS   = %d", &naxis);
	    if (naxis < 0) naxis = 0;
	    BEGIN(FLUSH);
	
	  } else {
	    sscanf(yytext, "NAXIS   = %d", &i);
	
	    if (i < 0) {
	      errmsg = "negative value of NAXIS ignored";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  }
	}

^WCSAXES{ALT}=" "" "*{INTEGER} {
	  sscanf(yytext, "WCSAXES%c= %d", &a, &i);
	
	  if (i < 0) {
	    errmsg = "negative value of WCSAXESa ignored";
	    BEGIN(ERROR);
	
	  } else {
	    valtype = INTEGER;
	    vptr    = 0x0;
	
	    keyname = "WCSAXESa";
	    BEGIN(COMMENT);
	  }
	}

^CRPIX	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.crpix);
	
	  keyname = "CRPIXja";
	  BEGIN(CCCCCia);
	}

^PC	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.pc);
	  altlin = 1;
	
	  keyname = "PCi_ja";
	  BEGIN(CCi_ja);
	}

^CD	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cd);
	  altlin = 2;
	
	  keyname = "CDi_ja";
	  BEGIN(CCi_ja);
	}

^CDELT	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cdelt);
	
	  keyname = "CDELTia";
	  BEGIN(CCCCCia);
	}

^CROTA	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.crota);
	  altlin = 4;
	
	  keyname = "CROTAn";
	  BEGIN(CROTAi);
	}

^CUNIT	{
	  valtype = STRING;
	  vptr    = &(wcstem.cunit);
	
	  keyname = "CUNITia";
	  BEGIN(CCCCCia);
	}

^CTYPE	{
	  valtype = STRING;
	  vptr    = &(wcstem.ctype);
	
	  keyname = "CTYPEia";
	  BEGIN(CCCCCia);
	}

^CRVAL	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.crval);
	
	  keyname = "CRVALia";
	  BEGIN(CCCCCia);
	}

^LONPOLE {
	  valtype = FLOAT;
	  vptr    = &(wcstem.lonpole);
	
	  keyname = "LONPOLEa";
	  BEGIN(CCCCCCCa);
	}

^LATPOLE {
	  valtype = FLOAT;
	  vptr    = &(wcstem.latpole);
	
	  keyname = "LATPOLEa";
	  BEGIN(CCCCCCCa);
	}

^RESTFRQ {
	  valtype = FLOAT;
	  vptr    = &(wcstem.restfrq);
	
	  keyname = "RESTFRQa";
	  BEGIN(CCCCCCCa);
	}

^RESTFREQ {
	  if (relax & WCSHDR_strict) {
	    errmsg = "the RESTFREQ keyword is deprecated, use RESTFRQa";
	    BEGIN(ERROR);
	
	  } else {
	    valtype = FLOAT;
	    vptr    = &(wcstem.restfrq);
	
	    unput(' ');
	
	    keyname = "RESTFREQ";
	    BEGIN(CCCCCCCa);
	  }
	}

^RESTWAV {
	  valtype = FLOAT;
	  vptr    = &(wcstem.restwav);
	
	  keyname = "RESTWAVa";
	  BEGIN(CCCCCCCa);
	}

^PV	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.pv);
	  npptr   = npv;
	
	  keyname = "PVi_ma";
	  BEGIN(CCi_ma);
	}

^PROJP	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.pv);
	  npptr   = npv;
	
	  keyname = "PROJPn";
	  BEGIN(PROJPn);
	}

^PS	{
	  valtype = STRING;
	  vptr    = &(wcstem.ps);
	  npptr   = nps;
	
	  keyname = "PSi_ma";
	  BEGIN(CCi_ma);
	}

^VELREF{ALT}" " {
	  sscanf(yytext, "VELREF%c", &a);
	
	  if (relax & WCSHDR_strict) {
	    errmsg = "the VELREF keyword is deprecated, use SPECSYSa";
	    BEGIN(ERROR);
	
	  } else if ((a == ' ') || (relax & WCSHDR_VELREFa)) {
	    valtype = INTEGER;
	    vptr    = &(wcstem.velref);
	
	    unput(a);
	
	    keyname = "VELREF";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VELREF keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^CNAME	{
	  valtype = STRING;
	  vptr    = &(wcstem.cname);
	
	  keyname = "CNAMEia";
	  BEGIN(CCCCCia);
	}

^CRDER	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.crder);
	
	  keyname = "CRDERia";
	  BEGIN(CCCCCia);
	}

^CSYER	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.csyer);
	
	  keyname = "CSYERia";
	  BEGIN(CCCCCia);
	}

^CZPHS	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.czphs);
	
	  keyname = "CZPHSia";
	  BEGIN(CCCCCia);
	}

^CPERI	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cperi);
	
	  keyname = "CPERIia";
	  BEGIN(CCCCCia);
	}

^WCSNAME {
	  valtype = STRING;
	  vptr    = wcstem.wcsname;
	
	  keyname = "WCSNAMEa";
	  BEGIN(CCCCCCCa);
	}

^TIMESYS" " {
	  valtype = STRING;
	  vptr    = wcstem.timesys;
	
	  keyname = "TIMESYS";
	  BEGIN(CCCCCCCC);
	}

^TREFPOS" " {
	  valtype = STRING;
	  vptr    = wcstem.trefpos;
	
	  keyname = "TREFPOS";
	  BEGIN(CCCCCCCC);
	}

^TREFDIR" " {
	  valtype = STRING;
	  vptr    = wcstem.trefdir;
	
	  keyname = "TREFDIR";
	  BEGIN(CCCCCCCC);
	}

^PLEPHEM" " {
	  valtype = STRING;
	  vptr    = wcstem.plephem;
	
	  keyname = "PLEPHEM";
	  BEGIN(CCCCCCCC);
	}

^TIMEUNIT {
	  valtype = STRING;
	  vptr    = wcstem.timeunit;
	
	  keyname = "TIMEUNIT";
	  BEGIN(CCCCCCCC);
	}

^DATEREF" " |
^DATE-REF {
	  if ((yytext[4] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = STRING;
	    vptr    = wcstem.dateref;
	
	    keyname = "DATEREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the DATE-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^MJDREF"  " |
^MJD-REF" " {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT2;
	    vptr    = wcstem.mjdref;
	
	    keyname = "MJDREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^MJDREFI" " |
^MJD-REFI {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    // Actually integer, but treated as float.
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
	
	    keyname = "MJDREFI";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REFI keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^MJDREFF" " |
^MJD-REFF {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref + 1;
	
	    keyname = "MJDREFF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REFF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^JDREF"   " |
^JD-REF"  " {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT2;
	    vptr    = wcstem.mjdref;
	    special = wcspih_jdref;
	
	    keyname = "JDREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^JDREFI"  " |
^JD-REFI {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    // Actually integer, but treated as float.
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
	    special = wcspih_jdrefi;
	
	    keyname = "JDREFI";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REFI keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^JDREFF"  " |
^JD-REFF {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
	    special = wcspih_jdreff;
	
	    keyname = "JDREFF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REFF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^TIMEOFFS {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timeoffs);
	
	  keyname = "TIMEOFFS";
	  BEGIN(CCCCCCCC);
	}

^DATE-OBS {
	  valtype = STRING;
	  vptr    = wcstem.dateobs;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-OBS";
	  BEGIN(CCCCCCCC);
	}

^DATE-BEG {
	  valtype = STRING;
	  vptr    = wcstem.datebeg;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-BEG";
	  BEGIN(CCCCCCCC);
	}

^DATE-AVG {
	  valtype = STRING;
	  vptr    = wcstem.dateavg;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-AVG";
	  BEGIN(CCCCCCCC);
	}

^DATE-END {
	  valtype = STRING;
	  vptr    = wcstem.dateend;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-END";
	  BEGIN(CCCCCCCC);
	}

^MJD-OBS" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdobs);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "MJD-OBS";
	  BEGIN(CCCCCCCC);
	}

^MJD-BEG" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdbeg);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "MJD-BEG";
	  BEGIN(CCCCCCCC);
	}

^MJD-AVG" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdavg);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "MJD-AVG";
	  BEGIN(CCCCCCCC);
	}

^MJD-END" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdend);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "MJD-END";
	  BEGIN(CCCCCCCC);
	}

^JEPOCH"  " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.jepoch);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "JEPOCH";
	  BEGIN(CCCCCCCC);
	}

^BEPOCH"  " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.bepoch);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "BEPOCH";
	  BEGIN(CCCCCCCC);
	}

^TSTART"  " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.tstart);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TSTART";
	  BEGIN(CCCCCCCC);
	}

^TSTOP"   " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.tstop);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TSTOP";
	  BEGIN(CCCCCCCC);
	}

^XPOSURE" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.xposure);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "XPOSURE";
	  BEGIN(CCCCCCCC);
	}

^TELAPSE" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.telapse);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TELAPSE";
	  BEGIN(CCCCCCCC);
	}

^TIMSYER" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timsyer);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMSYER";
	  BEGIN(CCCCCCCC);
	}

^TIMRDER" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timrder);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMRDER";
	  BEGIN(CCCCCCCC);
	}

^TIMEDEL" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timedel);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMEDEL";
	  BEGIN(CCCCCCCC);
	}

^TIMEPIXR {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timepixr);
	  chekval = wcspih_timepixr;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMEPIXR";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-X {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-X";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-Y {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 1;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-Y";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-Z {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 2;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-Z";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-L {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 3;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-L";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-B {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 4;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-B";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-H {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 5;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-H";
	  BEGIN(CCCCCCCC);
	}

^OBSORBIT {
	  valtype = STRING;
	  vptr    = wcstem.obsorbit;
	
	  keyname = "OBSORBIT";
	  BEGIN(CCCCCCCC);
	}

^RADESYS {
	  valtype = STRING;
	  vptr    = wcstem.radesys;
	
	  keyname = "RADESYSa";
	  BEGIN(CCCCCCCa);
	}

^RADECSYS {
	  if (relax & WCSHDR_RADECSYS) {
	    valtype = STRING;
	    vptr    = wcstem.radesys;
	
	    unput(' ');
	
	    keyname = "RADECSYS";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the RADECSYS keyword is deprecated, use RADESYSa";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^EPOCH{ALT}"  " {
	  sscanf(yytext, "EPOCH%c", &a);
	
	  if (relax & WCSHDR_strict) {
	    errmsg = "the EPOCH keyword is deprecated, use EQUINOXa";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_EPOCHa) {
	    valtype = FLOAT;
	    vptr    = &(wcstem.equinox);
	    special = wcspih_epoch;
	
	    unput(a);
	
	    keyname = "EPOCH";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "EPOCH keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^EQUINOX {
	  valtype = FLOAT;
	  vptr    = &(wcstem.equinox);
	
	  keyname = "EQUINOXa";
	  BEGIN(CCCCCCCa);
	}

^SPECSYS {
	  valtype = STRING;
	  vptr    = wcstem.specsys;
	
	  keyname = "SPECSYSa";
	  BEGIN(CCCCCCCa);
	}

^SSYSOBS {
	  valtype = STRING;
	  vptr    = wcstem.ssysobs;
	
	  keyname = "SSYSOBSa";
	  BEGIN(CCCCCCCa);
	}

^VELOSYS {
	  valtype = FLOAT;
	  vptr    = &(wcstem.velosys);
	
	  keyname = "VELOSYSa";
	  BEGIN(CCCCCCCa);
	}

^VSOURCE{ALT} {
	  if (relax & WCSHDR_VSOURCE) {
	    valtype = FLOAT;
	    vptr    = &(wcstem.zsource);
	    special = wcspih_vsource;
	
	    yyless(7);
	
	    keyname = "VSOURCEa";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the VSOURCEa keyword is deprecated, use ZSOURCEa";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^ZSOURCE {
	  valtype = FLOAT;
	  vptr    = &(wcstem.zsource);
	
	  keyname = "ZSOURCEa";
	  BEGIN(CCCCCCCa);
	}

^SSYSSRC {
	  valtype = STRING;
	  vptr    = wcstem.ssyssrc;
	
	  keyname = "SSYSSRCa";
	  BEGIN(CCCCCCCa);
	}

^VELANGL {
	  valtype = FLOAT;
	  vptr    = &(wcstem.velangl);
	
	  keyname = "VELANGLa";
	  BEGIN(CCCCCCCa);
	}

^RSUN_REF {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.rsun_ref);
	
	  keyname = "RSUN_REF";
	  BEGIN(CCCCCCCC);
	}

^DSUN_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.dsun_obs);
	
	  keyname = "DSUN_OBS";
	  BEGIN(CCCCCCCC);
	}

^CRLN_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.crln_obs);
	
	  keyname = "CRLN_OBS";
	  BEGIN(CCCCCCCC);
	}

^HGLN_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.hgln_obs);
	
	  keyname = "HGLN_OBS";
	  BEGIN(CCCCCCCC);
	}

^CRLT_OBS |
^HGLT_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.hglt_obs);
	
	  keyname = "HGLT_OBS";
	  BEGIN(CCCCCCCC);
	}

^A_RADIUS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.a_radius);
	
	  keyname = "A_RADIUS";
	  BEGIN(CCCCCCCC);
	}

^B_RADIUS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.b_radius);
	
	  keyname = "B_RADIUS";
	  BEGIN(CCCCCCCC);
	}

^C_RADIUS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.c_radius);
	
	  keyname = "C_RADIUS";
	  BEGIN(CCCCCCCC);
	}

^BLON_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.blon_obs);
	
	  keyname = "BLON_OBS";
	  BEGIN(CCCCCCCC);
	}

^BLAT_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.blat_obs);
	
	  keyname = "BLAT_OBS";
	  BEGIN(CCCCCCCC);
	}

^BDIS_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.bdis_obs);
	
	  keyname = "BDIS_OBS";
	  BEGIN(CCCCCCCC);
	}

^CPDIS	{
	  valtype = STRING;
	  distype = PRIOR;
	  vptr    = &(distem.dtype);
	
	  keyname = "CPDISja";
	  BEGIN(CCCCCia);
	}

^CQDIS	{
	  valtype = STRING;
	  distype = SEQUENT;
	  vptr    = &(distem.dtype);
	
	  keyname = "CQDISia";
	  BEGIN(CCCCCia);
	}

^DP	{
	  valtype = RECORD;
	  distype = PRIOR;
	  vptr    = &(distem.dp);
	  npptr   = ndp;
	
	  keyname = "DPja";
	  BEGIN(CCia);
	}

^DQ	{
	  valtype = RECORD;
	  distype = SEQUENT;
	  vptr    = &(distem.dp);
	  npptr   = ndq;
	
	  keyname = "DQia";
	  BEGIN(CCia);
	}

^CPERR	{
	  valtype = FLOAT;
	  distype = PRIOR;
	  vptr    = &(distem.maxdis);
	
	  keyname = "CPERRja";
	  BEGIN(CCCCCia);
	}

^CQERR	{
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = &(distem.maxdis);
	
	  keyname = "CQERRia";
	  BEGIN(CCCCCia);
	}

^DVERR	{
	  valtype = FLOAT;
	  distype = PRIOR;
	  vptr    = &(distem.totdis);
	
	  keyname = "DVERRa";
	  BEGIN(CCCCCCCa);
	}

^A_ORDER" " {
	  // SIP: axis 1 polynomial degree (not stored).
	  valtype = INTEGER;
	  distype = PRIOR;
	  vptr    = 0x0;
	
	  i = 1;
	  a = ' ';
	
	  keyname = "A_ORDER";
	  BEGIN(VALUE);
	}

^B_ORDER" " {
	  // SIP: axis 2 polynomial degree (not stored).
	  valtype = INTEGER;
	  distype = PRIOR;
	  vptr    = 0x0;
	
	  i = 2;
	  a = ' ';
	
	  keyname = "B_ORDER";
	  BEGIN(VALUE);
	}

^AP_ORDER {
	  // SIP: axis 1 inverse polynomial degree (not stored).
	  valtype = INTEGER;
	  distype = PRIOR;
	  vptr    = 0x0;
	
	  i = 1;
	  a = ' ';
	
	  keyname = "AP_ORDER";
	  BEGIN(VALUE);
	}

^BP_ORDER {
	  // SIP: axis 2 inverse polynomial degree (not stored).
	  valtype = INTEGER;
	  distype = PRIOR;
	  vptr    = 0x0;
	
	  i = 2;
	  a = ' ';
	
	  keyname = "BP_ORDER";
	  BEGIN(VALUE);
	}

^A_DMAX"  " {
	  // SIP: axis 1 maximum distortion.
	  valtype = FLOAT;
	  distype = PRIOR;
	  vptr    = &(distem.maxdis);
	
	  i = 1;
	  a = ' ';
	
	  keyname = "A_DMAX";
	  BEGIN(VALUE);
	}

^B_DMAX"  " {
	  // SIP: axis 2 maximum distortion.
	  valtype = FLOAT;
	  distype = PRIOR;
	  vptr    = &(distem.maxdis);
	
	  i = 2;
	  a = ' ';
	
	  keyname = "B_DMAX";
	  BEGIN(VALUE);
	}

^A_	{
	  // SIP: axis 1 polynomial coefficient.
	  i = 1;
	  sipflag = 2;
	
	  keyname = "A_p_q";
	  BEGIN(SIP2);
	}

^B_	{
	  // SIP: axis 2 polynomial coefficient.
	  i = 2;
	  sipflag = 2;
	
	  keyname = "B_p_q";
	  BEGIN(SIP2);
	}

^AP_	{
	  // SIP: axis 1 inverse polynomial coefficient.
	  i = 1;
	  sipflag = 3;
	
	  keyname = "AP_p_q";
	  BEGIN(SIP3);
	}

^BP_	{
	  // SIP: axis 2 inverse polynomial coefficient.
	  i = 2;
	  sipflag = 3;
	
	  keyname = "BP_p_q";
	  BEGIN(SIP3);
	}

^CNPIX1"  " {
	  // DSS: LLH corner pixel coordinate 1.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "CNPIX1";
	  BEGIN(VALUE);
	}

^CNPIX2"  " {
	  // DSS: LLH corner pixel coordinate 2.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+1;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "CNPIX1";
	  BEGIN(VALUE);
	}

^PPO3"    " {
	  // DSS: plate centre x-coordinate in micron.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+2;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PPO3";
	  BEGIN(VALUE);
	}

^PPO6"    " {
	  // DSS: plate centre y-coordinate in micron.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+3;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PPO6";
	  BEGIN(VALUE);
	}

^XPIXELSZ {
	  // DSS: pixel x-dimension in micron.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+4;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "XPIXELSZ";
	  BEGIN(VALUE);
	}

^YPIXELSZ {
	  // DSS: pixel y-dimension in micron.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+5;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "YPIXELSZ";
	  BEGIN(VALUE);
	}

^PLTRAH"  " {
	  // DSS: plate centre, right ascension - hours.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+6;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTRAH";
	  BEGIN(VALUE);
	}

^PLTRAM"  " {
	  // DSS: plate centre, right ascension - minutes.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+7;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTRAM";
	  BEGIN(VALUE);
	}

^PLTRAS"  " {
	  // DSS: plate centre, right ascension - seconds.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+8;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTRAS";
	  BEGIN(VALUE);
	}

^PLTDECSN {
	  // DSS: plate centre, declination - sign.
	  valtype = STRING;
	  distype = SEQUENT;
	  vptr    = dsstmp+9;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTDECSN";
	  BEGIN(PLTDECSN);
	}

^PLTDECD" " {
	  // DSS: plate centre, declination - degrees.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+10;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTDECD";
	  BEGIN(VALUE);
	}

^PLTDECM" " {
	  // DSS: plate centre, declination - arcmin.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+11;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTDECM";
	  BEGIN(VALUE);
	}

^PLTDECS" " {
	  // DSS: plate centre, declination - arcsec.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+12;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTDECS";
	  BEGIN(VALUE);
	}

^PLATEID" " {
	  // DSS: plate identification (insufficient to trigger DSS).
	  valtype = STRING;
	  distype = SEQUENT;
	  vptr    = dsstmp+13;
	  dssflag = 2;
	  distran = 0;
	
	  keyname = "PLATEID";
	  BEGIN(VALUE);
	}

^AMDX	{
	  // DSS: axis 1 polynomial coefficient.
	  i = 1;
	  dssflag = 3;
	
	  keyname = "AMDXm";
	  BEGIN(DSSAMDXY);
	}

^AMDY	{
	  // DSS: axis 2 polynomial coefficient.
	  i = 2;
	  dssflag = 3;
	
	  keyname = "AMDYm";
	  BEGIN(DSSAMDXY);
	}

^WAT[12]_{Z3} {
	  // TNX or ZPX: string-encoded data array.
	  sscanf(yytext, "WAT%d_%d", &i, &m);
	  if (watn < m) watn = m;
	  watflag = 1;
	
	  valtype = STRING;
	  distype = SEQUENT;
	  vptr = wat[i-1] + 68*(m-1);
	
	  a = ' ';
	  distran = WAT;
	
	  keyname = "WATi_m";
	  BEGIN(VALUE);
	}

^END" "{77} {
	  if (yyextra->nkeyrec) {
	    yyextra->nkeyrec = 0;
	    errmsg = "keyrecords following the END keyrecord were ignored";
	    BEGIN(ERROR);
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^.	{
	  BEGIN(DISCARD);
	}

<CCia>{I1}{ALT}"    " |
<CCia>{I2}{ALT}"   "  |
<CCCCCia>{I1}{ALT}" " |
<CCCCCia>{I2}{ALT} {
	  sscanf(yytext, "%d%c", &i, &a);
	  BEGIN(VALUE);
	}

<CCia>0{I1}{ALT}"   "    |
<CCia>0{Z1}{I1}{ALT}"  " |
<CCia>0{Z2}{I1}{ALT}" "  |
<CCia>0{Z3}{I1}{ALT}     |
<CCia>0{Z4}{I1}          |
<CCCCCia>0{I1}{ALT}      |
<CCCCCia>0{Z1}{I1} {
	  if (relax & WCSHDR_reject) {
	    // Violates the basic FITS standard.
	    errmsg = "indices in parameterized keywords must not have "
	             "leading zeroes";
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CCia>{Z1}{ALT}"    " |
<CCia>{Z2}{ALT}"   "  |
<CCia>{Z3}{ALT}"  "   |
<CCia>{Z4}{ALT}" "    |
<CCia>{Z5}{ALT}       |
<CCia>{Z6}            |
<CCCCCia>{Z1}{ALT}" " |
<CCCCCia>{Z2}{ALT}    |
<CCCCCia>{Z3} {
	  // Anything that has fallen through to this point must contain
	  // an invalid axis number.
	  errmsg = "axis number must exceed 0";
	  BEGIN(ERROR);
	}

<CCia>. {
	  // Let it go.
	  BEGIN(DISCARD);
	}

<CCCCCia>. {
	  if (relax & WCSHDR_reject) {
	    // Looks too much like a FITS WCS keyword not to flag it.
	    errmsg = errtxt;
	    snprintf(errmsg, 80, "keyword looks very much like %s but isn't",
	      keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Let it go.
	    BEGIN(DISCARD);
	  }
	}

<CCi_ja>{I1}_{I1}{ALT}"  " |
<CCi_ja>{I1}_{I2}{ALT}" " |
<CCi_ja>{I2}_{I1}{ALT}" " |
<CCi_ja>{I2}_{I2}{ALT} {
	  sscanf(yytext, "%d_%d%c", &i, &j, &a);
	  BEGIN(VALUE);
	}


<CCi_ja>0{I1}_{I1}{ALT}" " |
<CCi_ja>{I1}_0{I1}{ALT}" " |
<CCi_ja>00{I1}_{I1}{ALT} |
<CCi_ja>0{I1}_0{I1}{ALT} |
<CCi_ja>{I1}_00{I1}{ALT} |
<CCi_ja>000{I1}_{I1} |
<CCi_ja>00{I1}_0{I1} |
<CCi_ja>0{I1}_00{I1} |
<CCi_ja>{I1}_000{I1} |
<CCi_ja>0{I1}_{I2}{ALT} |
<CCi_ja>{I1}_0{I2}{ALT} |
<CCi_ja>00{I1}_{I2} |
<CCi_ja>0{I1}_0{I2} |
<CCi_ja>{I1}_00{I2} |
<CCi_ja>0{I2}_{I1}{ALT} |
<CCi_ja>{I2}_0{I1}{ALT} |
<CCi_ja>00{I2}_{I1} |
<CCi_ja>0{I2}_0{I1} |
<CCi_ja>{I2}_00{I1} |
<CCi_ja>0{I2}_{I2} |
<CCi_ja>{I2}_0{I2} {
	  if (((altlin == 1) && (relax & WCSHDR_PC0i_0ja)) ||
	      ((altlin == 2) && (relax & WCSHDR_CD0i_0ja))) {
	    sscanf(yytext, "%d_%d%c", &i, &j, &a);
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "indices in parameterized keywords must not have "
	             "leading zeroes";
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CCi_ja>{Z1}_{Z1}{ALT}"  " |
<CCi_ja>{Z2}_{Z1}{ALT}" " |
<CCi_ja>{Z1}_{Z2}{ALT}" " |
<CCi_ja>{Z3}_{Z1}{ALT} |
<CCi_ja>{Z2}_{Z2}{ALT} |
<CCi_ja>{Z1}_{Z3}{ALT} |
<CCi_ja>{Z4}_{Z1} |
<CCi_ja>{Z3}_{Z2} |
<CCi_ja>{Z2}_{Z3} |
<CCi_ja>{Z1}_{Z4} {
	  // Anything that has fallen through to this point must contain
	  // an invalid axis number.
	  errmsg = "axis number must exceed 0";
	  BEGIN(ERROR);
	}

<CCi_ja>{Z1}-{Z1}{ALT}"  " |
<CCi_ja>{Z2}-{Z1}{ALT}" " |
<CCi_ja>{Z1}-{Z2}{ALT}" " |
<CCi_ja>{Z3}-{Z1}{ALT} |
<CCi_ja>{Z2}-{Z2}{ALT} |
<CCi_ja>{Z1}-{Z3}{ALT} |
<CCi_ja>{Z4}-{Z1} |
<CCi_ja>{Z3}-{Z2} |
<CCi_ja>{Z2}-{Z3} |
<CCi_ja>{Z1}-{Z4} {
	  errmsg = errtxt;
	  snprintf(errmsg, 80,
	    "%s keyword must use an underscore, not a dash", keyname);
	  BEGIN(ERROR);
	}

<CCi_ja>{Z2}{I1}{Z2}{I1} {
	  // This covers the defunct forms CD00i00j and PC00i00j.
	  if (((altlin == 1) && (relax & WCSHDR_PC00i00j)) ||
	      ((altlin == 2) && (relax & WCSHDR_CD00i00j))) {
	    sscanf(yytext, "%3d%3d", &i, &j);
	    a = ' ';
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "this form of the %s keyword is deprecated, use %s",
	      keyname, keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CCi_ja>. {
	  BEGIN(DISCARD);
	}

<CCCCCCCa>{ALT} |
<CCCCCCCC>. {
	  if (YY_START == CCCCCCCa) {
	    sscanf(yytext, "%c", &a);
	  } else {
	    unput(yytext[0]);
	    a = 0;
	  }
	
	  BEGIN(VALUE);
	}

<CCCCCCCa>. {
	  if (relax & WCSHDR_reject) {
	    // Looks too much like a FITS WCS keyword not to flag it.
	    errmsg = errtxt;
	    snprintf(errmsg, 80, "invalid alternate code, keyword resembles "
	      "%s but isn't", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CCi_ma>{I1}_{Z1}{ALT}"  " |
<CCi_ma>{I1}_{I2}{ALT}" " |
<CCi_ma>{I2}_{Z1}{ALT}" " |
<CCi_ma>{I2}_{I2}{ALT} {
	  sscanf(yytext, "%d_%d%c", &i, &m, &a);
	  BEGIN(VALUE);
	}

<CCi_ma>0{I1}_{Z1}{ALT}" " |
<CCi_ma>{I1}_0{Z1}{ALT}" " |
<CCi_ma>00{I1}_{Z1}{ALT} |
<CCi_ma>0{I1}_0{Z1}{ALT} |
<CCi_ma>{I1}_00{Z1}{ALT} |
<CCi_ma>000{I1}_{Z1} |
<CCi_ma>00{I1}_0{Z1} |
<CCi_ma>0{I1}_00{Z1} |
<CCi_ma>{I1}_000{Z1} |
<CCi_ma>0{I1}_{I2}{ALT} |
<CCi_ma>{I1}_0{I2}{ALT} |
<CCi_ma>00{I1}_{I2} |
<CCi_ma>0{I1}_0{I2} |
<CCi_ma>{I1}_00{I2} |
<CCi_ma>0{I2}_{Z1}{ALT} |
<CCi_ma>{I2}_0{Z1}{ALT} |
<CCi_ma>00{I2}_{Z1} |
<CCi_ma>0{I2}_0{Z1} |
<CCi_ma>{I2}_00{Z1} |
<CCi_ma>0{I2}_{I2} |
<CCi_ma>{I2}_0{I2} {
	  if (((valtype == FLOAT)  && (relax & WCSHDR_PV0i_0ma)) ||
	      ((valtype == STRING) && (relax & WCSHDR_PS0i_0ma))) {
	    sscanf(yytext, "%d_%d%c", &i, &m, &a);
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "indices in parameterized keywords must not have "
	             "leading zeroes";
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CCi_ma>{Z1}_{Z1}{ALT}"  " |
<CCi_ma>{Z2}_{Z1}{ALT}" " |
<CCi_ma>{Z1}_{Z2}{ALT}" " |
<CCi_ma>{Z3}_{Z1}{ALT} |
<CCi_ma>{Z2}_{Z2}{ALT} |
<CCi_ma>{Z1}_{Z3}{ALT} |
<CCi_ma>{Z4}_{Z1} |
<CCi_ma>{Z3}_{Z2} |
<CCi_ma>{Z2}_{Z3} |
<CCi_ma>{Z1}_{Z4} {
	  // Anything that has fallen through to this point must contain
	  // an invalid axis number.
	  errmsg = "axis number must exceed 0";
	  BEGIN(ERROR);
	}

<CCi_ma>{Z1}-{Z1}{ALT}"  " |
<CCi_ma>{Z2}-{Z1}{ALT}" " |
<CCi_ma>{Z1}-{Z2}{ALT}" " |
<CCi_ma>{Z3}-{Z1}{ALT} |
<CCi_ma>{Z2}-{Z2}{ALT} |
<CCi_ma>{Z1}-{Z3}{ALT} |
<CCi_ma>{Z4}-{Z1} |
<CCi_ma>{Z3}-{Z2} |
<CCi_ma>{Z2}-{Z3} |
<CCi_ma>{Z1}-{Z4} {
	  errmsg = errtxt;
	  snprintf(errmsg, 80,
	    "%s keyword must use an underscore, not a dash", keyname);
	  BEGIN(ERROR);
	}

<CCi_ma>. {
	  BEGIN(DISCARD);
	}

<CROTAi>{Z1}{ALT}" " |
<CROTAi>{Z2}{ALT} |
<CROTAi>{Z3} {
	  a = ' ';
	  sscanf(yytext, "%d%c", &i, &a);
	
	  if (relax & WCSHDR_strict) {
	    errmsg = "the CROTAn keyword is deprecated, use PCi_ja";
	    BEGIN(ERROR);
	
	  } else if ((a == ' ') || (relax & WCSHDR_CROTAia)) {
	    yyless(0);
	    BEGIN(CCCCCia);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "CROTAn keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CROTAi>. {
	  yyless(0);
	  BEGIN(CCCCCia);
	}

<PROJPn>{Z1}"  " {
	  if (relax & WCSHDR_PROJPn) {
	    sscanf(yytext, "%d", &m);
	    i = 0;
	    a = ' ';
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the PROJPn keyword is deprecated, use PVi_ma";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

<PROJPn>{Z2}" " |
<PROJPn>{Z3} {
	  if (relax & (WCSHDR_PROJPn | WCSHDR_reject)) {
	    errmsg = "invalid PROJPn keyword";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

<PROJPn>. {
	  BEGIN(DISCARD);
	}

<SIP2>{Z1}_{Z1}"   " |
<SIP3>{Z1}_{Z1}"  " {
	  // SIP keywords.
	  valtype = FLOAT;
	  distype = PRIOR;
	  vptr    = &(distem.dp);
	  npptr   = ndp;
	
	  a = ' ';
	  distran = SIP;
	
	  sscanf(yytext, "%d_%d", &p, &q);
	  BEGIN(VALUE);
	}

<SIP2>. |
<SIP3>. {
	  BEGIN(DISCARD);
	}

<DSSAMDXY>{I1}"   " |
<DSSAMDXY>{I2}"  " {
	  // DSS keywords.
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = &(distem.dp);
	  npptr   = ndq;
	
	  a = ' ';
	  distran = DSS;
	
	  sscanf(yytext, "%d", &m);
	  BEGIN(VALUE);
	}

<DSSAMDXY>. {
	  BEGIN(DISCARD);
	}

<PLTDECSN>=" "+{STRING} {
	  // Special handling for this iconic DSS keyword.
	  if (1 < ipass) {
	    // Look for a minus sign.
	    sscanf(yytext, "= '%s", strtmp);
	    dbltmp = strcmp(strtmp, "-") ? 1.0 : -1.0;
	  }
	
	  BEGIN(COMMENT);
	}

<PLTDECSN>. {
	  BEGIN(DISCARD);
	}

<VALUE>=" "+ {
	  // Do checks on i, j & m.
	  if (99 < i || 99 < j || 99 < m) {
	    if (relax & WCSHDR_reject) {
	      if (99 < i || 99 < j) {
	        errmsg = "axis number exceeds 99";
	      } else if (m > 99) {
	        errmsg = "parameter number exceeds 99";
	      }
	      BEGIN(ERROR);
	
	    } else {
	      // Pretend we don't recognize it.
	      BEGIN(DISCARD);
	    }
	
	  } else {
	    if (valtype == INTEGER) {
	      BEGIN(INTEGER_VAL);
	    } else if (valtype == FLOAT) {
	      BEGIN(FLOAT_VAL);
	    } else if (valtype == FLOAT2) {
	      BEGIN(FLOAT2_VAL);
	    } else if (valtype == STRING) {
	      BEGIN(STRING_VAL);
	    } else if (valtype == RECORD) {
	      BEGIN(RECORD_VAL);
	    } else {
	      errmsg = errtxt;
	      snprintf(errmsg, 80, "internal parser ERROR, bad data type: %d",
	        valtype);
	      BEGIN(ERROR);
	    }
	  }
	}

<VALUE>. {
	  errmsg = "invalid KEYWORD = VALUE syntax";
	  BEGIN(ERROR);
	}

<INTEGER_VAL>{INTEGER} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
	
	  } else {
	    // Read the keyvalue.
	    sscanf(yytext, "%d", &inttmp);
	
	    BEGIN(COMMENT);
	  }
	}

<INTEGER_VAL>. {
	  errmsg = "an integer value was expected";
	  BEGIN(ERROR);
	}

<FLOAT_VAL>{FLOAT} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
	
	  } else {
	    // Read the keyvalue.
	    wcsutil_str2double(yytext, &dbltmp);

	    if (chekval && chekval(dbltmp)) {
	      errmsg = "invalid keyvalue";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(COMMENT);
	    }
	  }
	}

<FLOAT_VAL>. {
	  errmsg = "a floating-point value was expected";
	  BEGIN(ERROR);
	}

<FLOAT2_VAL>{FLOAT} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
	
	  } else {
	    // Read the keyvalue as integer and fractional parts.
	    wcsutil_str2double2(yytext, dbl2tmp);
	
	    BEGIN(COMMENT);
	  }
	}

<FLOAT2_VAL>. {
	  errmsg = "a floating-point value was expected";
	  BEGIN(ERROR);
	}

<STRING_VAL>{STRING} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
	
	  } else {
	    strtmp[0] = '\0';
	    int nch = yyleng - 2;
	    if (0 < nch && nch < 80) {
	      // Copy the keyvalue minus the quotes.
	      strncpy(strtmp, yytext+1, nch);
	      strtmp[nch] = '\0';
	
	      // Strip off trailing blanks.
	      for (int jx = nch-1; jx >= 0; jx--) {
	        if (strtmp[jx] != ' ') {
	          break;
	        }
	        strtmp[jx] = '\0';
	      }
	    }
	
	    // Squeeze out repeated quotes.
	    int ix = 0;
	    for (int jx = 0; jx < 72; jx++) {
	      if (ix < jx) {
	        strtmp[ix] = strtmp[jx];
	      }
	
	      if (strtmp[jx] == '\0') {
	        break;
	      } else if (strtmp[jx] == '\'' && strtmp[jx+1] == '\'') {
	        jx++;
	      }
	
	      ix++;
	    }
	
	    BEGIN(COMMENT);
	  }
	}

<STRING_VAL>. {
	  errmsg = "a string value was expected";
	  BEGIN(ERROR);
	}

<RECORD_VAL>{RECORD} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
	
	  } else {
	    yyless(1);
	
	    BEGIN(RECFIELD);
	  }
	}

<RECORD_VAL>. {
	  errmsg = "a record was expected";
	  BEGIN(ERROR);
	}

<RECFIELD>{FIELD} {
	  strncpy(strtmp, yytext, 72);
	  strtmp[72] = '\0';
	  BEGIN(RECCOLON);
	}

<RECFIELD>. {
	  errmsg = "invalid record field";
	  BEGIN(ERROR);
	}

<RECCOLON>:" "+ {
	  BEGIN(RECVALUE);
	}

<RECCOLON>. {
	  errmsg = "invalid record syntax";
	  BEGIN(ERROR);
	}

<RECVALUE>{INTEGER} {
	  rectype = 0;
	  sscanf(yytext, "%d", &inttmp);
	  BEGIN(RECEND);
	}

<RECVALUE>{FLOAT} {
	  rectype = 1;
	  wcsutil_str2double(yytext, &dbltmp);
	  BEGIN(RECEND);
	}

<RECVALUE>. {
	  errmsg = "invalid record value";
	  BEGIN(ERROR);
	}

<RECEND>' {
	  BEGIN(COMMENT);
	}

<COMMENT>{INLINE}$ {
	  if (ipass == 1) {
	    // Do first-pass bookkeeping.
	    wcspih_pass1(naxis, i, j, a, distype, alts, dpq, npptr);
	    BEGIN(FLUSH);
	
	  } else if (*wcs) {
	    // Store the value now that the keyrecord has been validated.
	    int gotone = 0;
	    for (int ialt = 0; ialt < *nwcs; ialt++) {
	      // The loop here is for keywords that apply
	      // to every alternate; these have a == 0.
	      if (a >= 'A') {
	        ialt = alts[a-'A'+1];
	        if (ialt < 0) break;
	      }
	      gotone = 1;
	
	      if (vptr) {
	        if (sipflag) {
	          // Translate a SIP keyword into DPja.
	          struct disprm *disp = (*wcs)->lin.dispre;
	          int ipx = (disp->ndp)++;
	
	          // SIP doesn't have alternates.
		  char keyword[16];
	          snprintf(keyword, 16, "DP%d", i);
	          snprintf(strtmp, 80, "SIP.%s.%d_%d",
	                  (sipflag==2)?"FWD":"REV", p, q);
	          if (valtype == INTEGER) {
	            dpfill(disp->dp+ipx, keyword, strtmp, i, 0, inttmp, 0.0);
	          } else {
	            dpfill(disp->dp+ipx, keyword, strtmp, i, 1, 0, dbltmp);
	          }
	
	        } else if (dssflag) {
	          // All DSS keywords require special handling.
	          if (dssflag == 1) {
	            // Temporary parameter for DSS used by wcspih_final().
	            *((double *)vptr) = dbltmp;
	
	          } else if (dssflag == 2) {
	            // Temporary parameter for DSS used by wcspih_final().
	            strncpy((char *)vptr, strtmp, 8);
	
	          } else {
	            // Translate a DSS keyword into DQia.
	            if (m <= 13 || dbltmp != 0.0) {
	              struct disprm *disp = (*wcs)->lin.disseq;
	              int ipx = (disp->ndp)++;
	
	              // DSS doesn't have alternates.
		      char keyword[16];
	              snprintf(keyword, 16, "DQ%d", i);
	              snprintf(strtmp, 80, "DSS.AMD.%d", m);
	              dpfill(disp->dp+ipx, keyword, strtmp, i, 1, 0, dbltmp);
	
	              // Also required by wcspih_final().
	              if (m <= 3) {
	                dsstmp[13+(i-1)*3+m] = dbltmp;
	              }
	            }
	          }
	
	        } else if (watflag) {
	          // String array for TNX and ZPX used by wcspih_final().
	          strncpy((char *)vptr, strtmp, 68);
	
	        } else {
	          // An "ordinary" keyword.
	          struct wcsprm *wcsp = *wcs + ialt;
		  struct disprm *disp;
	          void *wptr;
	          ptrdiff_t voff;
	          if (auxprm) {
	            // Additional auxiliary parameter.
	            struct auxprm *auxp = wcsp->aux;
	            voff = (char *)vptr - (char *)(&auxtem);
	            wptr = (void *)((char *)auxp + voff);
	
	          } else if (distype) {
	            // Distortion parameter of some kind.
	            if (distype == PRIOR) {
	              // Prior distortion.
	              disp = wcsp->lin.dispre;
	            } else {
	              // Sequent distortion.
	              disp = wcsp->lin.disseq;
	            }
	            voff = (char *)vptr - (char *)(&distem);
	            wptr = (void *)((char *)disp + voff);
	
	          } else {
	            // A parameter that lives directly in wcsprm.
	            voff = (char *)vptr - (char *)(&wcstem);
	            wptr = (void *)((char *)wcsp + voff);
	          }
	
	          if (valtype == INTEGER) {
	            *((int *)wptr) = inttmp;
	
	          } else if (valtype == FLOAT) {
	            // Apply keyword parameterization.
	            if (npptr == npv) {
	              int ipx = (wcsp->npv)++;
	              wcsp->pv[ipx].i = i;
	              wcsp->pv[ipx].m = m;
	              wptr = &(wcsp->pv[ipx].value);
	
	            } else if (j) {
	              wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis)
	                                        + (j - 1);
	
	            } else if (i) {
	              wptr = *((double **)wptr) + (i - 1);
	            }
	
	            if (special) {
	              special(wptr, &dbltmp);
	            } else {
	              *((double *)wptr) = dbltmp;
	            }
	
	            // Flag presence of PCi_ja, or CDi_ja and/or CROTAia.
	            if (altlin) {
	              wcsp->altlin |= altlin;
	              altlin = 0;
	            }
	
	          } else if (valtype == FLOAT2) {
	            // Split MJDREF and JDREF into integer and fraction.
	            if (special) {
	              special(wptr, dbl2tmp);
	            } else {
	              *((double *)wptr) = dbl2tmp[0];
	              *((double *)wptr + 1) = dbl2tmp[1];
	            }
	
	          } else if (valtype == STRING) {
	            // Apply keyword parameterization.
	            if (npptr == nps) {
	              int ipx = (wcsp->nps)++;
	              wcsp->ps[ipx].i = i;
	              wcsp->ps[ipx].m = m;
	              wptr = wcsp->ps[ipx].value;
	
	            } else if (j) {
	              wptr = *((char (**)[72])wptr) +
	                      (i - 1)*(wcsp->naxis) + (j - 1);
	
	            } else if (i) {
	              wptr = *((char (**)[72])wptr) + (i - 1);
	            }
	
	            char *cptr = (char *)wptr;
	            strncpy(cptr, strtmp, 72);
	
	          } else if (valtype == RECORD) {
	            int ipx = (disp->ndp)++;
	
		    char keyword[16];
	            if (a == ' ') {
	              snprintf(keyword, 16, "%.2s%d", keyname, i);
	            } else {
	              snprintf(keyword, 16, "%.2s%d%c", keyname, i, a);
	            }
	
	            dpfill(disp->dp+ipx, keyword, strtmp, i, rectype, inttmp,
	                   dbltmp);
	          }
	        }
	      }
	
	      if (a) break;
	    }
	
	    if (gotone) {
	      nvalid++;
	      if (ctrl == 4) {
	        if (distran || dssflag) {
	          wcsfprintf(stderr, "%.80s\n  Accepted (%d) as a "
	            "recognized WCS convention.\n", keyrec, nvalid);
	        } else {
	          wcsfprintf(stderr, "%.80s\n  Accepted (%d) as a "
	            "valid WCS keyrecord.\n", keyrec, nvalid);
	        }
	      }
	
	      BEGIN(FLUSH);
	
	    } else {
	      errmsg = "syntactically valid WCS keyrecord has no effect";
	      BEGIN(ERROR);
	    }
	
	  } else {
	    BEGIN(FLUSH);
	  }
	}

<COMMENT>.*" "*\/.*$ {
	  errmsg = "invalid keyvalue";
	  BEGIN(ERROR);
	}

<COMMENT>[^ \/\n]*{INLINE}$ {
	  errmsg = "invalid keyvalue";
	  BEGIN(ERROR);
	}

<COMMENT>" "+[^\/\n].*{INLINE}$ {
	  errmsg = "invalid keyvalue or malformed keycomment";
	  BEGIN(ERROR);
	}

<COMMENT>.*$ {
	  errmsg = "malformed keycomment";
	  BEGIN(ERROR);
	}

<DISCARD>.*$ {
	  if (ipass == npass) {
	    if (ctrl < 0) {
	      // Preserve discards.
	      keep = keyrec;
	
	    } else if (2 < ctrl) {
	      nother++;
	      wcsfprintf(stderr, "%.80s\n  Not a recognized WCS keyword.\n",
	        keyrec);
	    }
	  }
	  BEGIN(FLUSH);
	}

<ERROR>.*$ {
	  if (ipass == npass) {
	    (*nreject)++;
	
	    if (ctrl%10 == -1) {
	      // Preserve rejects.
	      keep = keyrec;
	    }
	
	    if (1 < abs(ctrl%10)) {
	      wcsfprintf(stderr, "%.80s\n  Rejected (%d), %s.\n",
	        keyrec, *nreject, errmsg);
	    }
	  }
	  BEGIN(FLUSH);
	}

<FLUSH>.*\n {
	  if (ipass == npass && keep) {
	    if (hptr < keep) {
	      strncpy(hptr, keep, 80);
	    }
	    hptr += 80;
	  }
	
	  naux += auxprm;
	
	  // Throw away the rest of the line and reset for the next one.
	  i = j = 0;
	  m = 0;
	  a = ' ';
	
	  keyrec += 80;
	
	  valtype = -1;
	  distype =  0;
	  vptr    = 0x0;
	  keep    = 0x0;
	
	  altlin  = 0;
	  npptr   = 0x0;
	  chekval = 0x0;
	  special = 0x0;
	  auxprm  = 0;
	  sipflag = 0;
	  dssflag = 0;
	  watflag = 0;
	
	  BEGIN(INITIAL);
	}

<<EOF>>	 {
	  // End-of-input.
	  int status;
	  if (ipass == 1) {
	    if ((status = wcspih_init1(naxis, alts, dpq, npv, nps, ndp, ndq,
	                               naux, distran, nwcs, wcs)) ||
	        (*nwcs == 0 && ctrl == 0)) {
	      return status;
	    }
	
	    if (2 < abs(ctrl%10)) {
	      if (*nwcs == 1) {
	        if (strcmp(wcs[0]->wcsname, "DEFAULTS") != 0) {
	          wcsfprintf(stderr, "Found one coordinate representation.\n");
	        }
	      } else {
	        wcsfprintf(stderr, "Found %d coordinate representations.\n",
	          *nwcs);
	      }
	    }
	
	    watstr = calloc(2*(watn*68 + 1), sizeof(char));
	    wat[0] = watstr;
	    wat[1] = watstr + watn*68 + 1;
	  }
	
	  if (ipass++ < npass) {
	    yyextra->hdr = header;
	    yyextra->nkeyrec = nkeyrec;
	    keyrec = header;
	    *nreject = 0;
	
	    i = j = 0;
	    m = 0;
	    a = ' ';
	
	    valtype = -1;
	    distype =  0;
	    vptr    = 0x0;
	
	    altlin  = 0;
	    npptr   = 0x0;
	    chekval = 0x0;
	    special = 0x0;
	    auxprm  = 0;
	    sipflag = 0;
	    dssflag = 0;
	    watflag = 0;
	
	    yyrestart(yyin, yyscanner);
	
	  } else {
	
	    if (ctrl < 0) {
	      *hptr = '\0';
	    } else if (ctrl == 1) {
	      wcsfprintf(stderr, "%d WCS keyrecord%s rejected.\n",
	        *nreject, (*nreject==1)?" was":"s were");
	    } else if (ctrl == 4) {
	      wcsfprintf(stderr, "\n");
	      wcsfprintf(stderr, "%5d keyrecord%s rejected for syntax or "
	        "other errors,\n", *nreject, (*nreject==1)?" was":"s were");
	      wcsfprintf(stderr, "%5d %s recognized as syntactically valid, "
	        "and\n", nvalid, (nvalid==1)?"was":"were");
	      wcsfprintf(stderr, "%5d other%s were not recognized as WCS "
	        "keyrecords.\n", nother, (nother==1)?"":"s");
	    }
	
	    status = wcspih_final(ndp, ndq, distran, dsstmp, wat, nwcs, wcs);
	    free(watstr);
	    return status;
	  }
	}

%%

/*----------------------------------------------------------------------------
* External interface to the scanner.
*---------------------------------------------------------------------------*/

int wcspih(
  char *header,
  int nkeyrec,
  int relax,
  int ctrl,
  int *nreject,
  int *nwcs,
  struct wcsprm **wcs)

{
  // Function prototypes.
  int yylex_init_extra(YY_EXTRA_TYPE extra, yyscan_t *yyscanner);
  int yylex_destroy(yyscan_t yyscanner);

  struct wcspih_extra extra;
  yyscan_t yyscanner;
  yylex_init_extra(&extra, &yyscanner);
  int status = wcspih_scanner(header, nkeyrec, relax, ctrl, nreject, nwcs,
                              wcs, yyscanner);
  yylex_destroy(yyscanner);

  return status;
}


/*----------------------------------------------------------------------------
* Determine the number of coordinate representations (up to 27) and the
* number of coordinate axes in each, which distortions are present, and the
* number of PVi_ma, PSi_ma, DPja, and DQia keywords in each representation.
*---------------------------------------------------------------------------*/

void wcspih_pass1(
  int naxis,
  int i,
  int j,
  char a,
  int distype,
  int alts[],
  int dpq[],
  int *npptr)

{
  // On the first pass alts[] is used to determine the number of axes
  // for each of the 27 possible alternate coordinate descriptions.
  if (a == 0) {
    return;
  }

  int ialt = 0;
  if (a != ' ') {
    ialt = a - 'A' + 1;
  }

  int *ip = alts + ialt;

  if (*ip < naxis) {
    *ip = naxis;
  }

  // i or j can be greater than naxis.
  if (*ip < i) {
    *ip = i;
  }

  if (*ip < j) {
    *ip = j;
  }

  // Type of distortions present.
  dpq[ialt] |= distype;

  // Count PVi_ma, PSi_ma, DPja, or DQia keywords.
  if (npptr) {
    npptr[ialt]++;
  }
}


/*----------------------------------------------------------------------------
* Allocate memory for an array of the required number of wcsprm structs and
* initialize each of them.
*---------------------------------------------------------------------------*/

int wcspih_init1(
  int naxis,
  int alts[],
  int dpq[],
  int npv[],
  int nps[],
  int ndp[],
  int ndq[],
  int naux,
  int distran,
  int *nwcs,
  struct wcsprm **wcs)

{
  int status = 0;

  // Find the number of coordinate descriptions.
  *nwcs = 0;
  for (int ialt = 0; ialt < 27; ialt++) {
    if (alts[ialt]) (*nwcs)++;
  }

  int defaults;
  if ((defaults = !(*nwcs) && naxis)) {
    // NAXIS is non-zero but there were no WCS keywords with an alternate
    // version code; create a default WCS with blank alternate version.
    wcspih_pass1(naxis, 0, 0, ' ', 0, alts, dpq, 0x0);
    *nwcs = 1;
  }

  if (*nwcs) {
    // Allocate memory for the required number of wcsprm structs.
    if ((*wcs = calloc(*nwcs, sizeof(struct wcsprm))) == 0x0) {
      return WCSHDRERR_MEMORY;
    }

    int ndis = 0;
    if (distran == SIP) {
      // DPja.NAXES and DPja.OFFSET.j to be added for SIP (see below and
      // wcspih_final()).
      ndp[0] += 6;

    } else if (distran == DSS) {
      // DPja.NAXES to be added for DSS (see below and wcspih_final()).
      ndq[0] += 2;
    }

    // Initialize each wcsprm struct.
    struct wcsprm *wcsp = *wcs;
    *nwcs = 0;
    for (int ialt = 0; ialt < 27; ialt++) {
      if (alts[ialt]) {
        wcsp->flag = -1;
        int npvmax = npv[ialt];
        int npsmax = nps[ialt];
        if ((status = wcsinit(1, alts[ialt], wcsp, npvmax, npsmax, -1))) {
          wcsvfree(nwcs, wcs);
          break;
        }

        // Record the alternate version code.
        if (ialt) {
          wcsp->alt[0] = 'A' + ialt - 1;
        }

        // Record in wcsname whether this is a default description.
        if (defaults) {
          strncpy(wcsp->wcsname, "DEFAULTS", 72);
        }

        // Any additional auxiliary keywords present?
        if (naux) {
          if (wcsauxi(1, wcsp)) {
            return WCSHDRERR_MEMORY;
          }
        }

        // Any distortions present?
        struct disprm *disp;
        if (dpq[ialt] & 1) {
          if ((disp = calloc(1, sizeof(struct disprm))) == 0x0) {
            return WCSHDRERR_MEMORY;
          }

          // Attach it to linprm.  Also inits it.
          ndis++;
          int ndpmax = ndp[ialt];
          disp->flag = -1;
          lindist(1, &(wcsp->lin), disp, ndpmax);
        }

        if (dpq[ialt] & 2) {
          if ((disp = calloc(1, sizeof(struct disprm))) == 0x0) {
            return WCSHDRERR_MEMORY;
          }

          // Attach it to linprm.  Also inits it.
          ndis++;
          int ndpmax = ndq[ialt];
          disp->flag = -1;
          lindist(2, &(wcsp->lin), disp, ndpmax);
        }

        // On the second pass alts[] indexes the array of wcsprm structs.
        alts[ialt] = (*nwcs)++;

        wcsp++;

      } else {
        // Signal that there is no wcsprm for this alt.
        alts[ialt] = -1;
      }
    }


    // Translated distortion?  Neither SIP nor DSS have alternates, so the
    // presence of keywords for either (not both together), as flagged by
    // distran, necessarily refers to the primary representation.
    if (distran == SIP) {
      strncpy((*wcs)->lin.dispre->dtype[0], "SIP", 72);
      strncpy((*wcs)->lin.dispre->dtype[1], "SIP", 72);

      // SIP doesn't have axis mapping.
      (*wcs)->lin.dispre->ndp = 6;
      dpfill((*wcs)->lin.dispre->dp,   "DP1", "NAXES",  0, 0, 2, 0.0);
      dpfill((*wcs)->lin.dispre->dp+3, "DP2", "NAXES",  0, 0, 2, 0.0);

    } else if (distran == DSS) {
      strncpy((*wcs)->lin.disseq->dtype[0], "DSS", 72);
      strncpy((*wcs)->lin.disseq->dtype[1], "DSS", 72);

      // The Paper IV translation of DSS doesn't require an axis mapping.
      (*wcs)->lin.disseq->ndp = 2;
      dpfill((*wcs)->lin.disseq->dp,   "DQ1", "NAXES",  0, 0, 2, 0.0);
      dpfill((*wcs)->lin.disseq->dp+1, "DQ2", "NAXES",  0, 0, 2, 0.0);
    }
  }

  return status;
}


/*----------------------------------------------------------------------------
* Interpret the JDREF, JDREFI, and JDREFF keywords.
*---------------------------------------------------------------------------*/

int wcspih_jdref(double *mjdref, const double *jdref)

{
  // Set MJDREF from JDREF.
  if (undefined(mjdref[0] && undefined(mjdref[1]))) {
    mjdref[0] = jdref[0] - 2400000.0;
    mjdref[1] = jdref[1] - 0.5;

    if (mjdref[1] < 0.0) {
      mjdref[0] -= 1.0;
      mjdref[1] += 1.0;
    }
  }

  return 0;
}

int wcspih_jdrefi(double *mjdref, const double *jdrefi)

{
  // Set the integer part of MJDREF from JDREFI.
  if (undefined(mjdref[0])) {
    mjdref[0] = *jdrefi - 2400000.5;
  }

  return 0;
}


int wcspih_jdreff(double *mjdref, const double *jdreff)

{
  // Set the fractional part of MJDREF from JDREFF.
  if (undefined(mjdref[1])) {
    mjdref[1] = *jdreff;
  }

  return 0;
}


/*----------------------------------------------------------------------------
* Interpret EPOCHa keywords.
*---------------------------------------------------------------------------*/

int wcspih_epoch(double *equinox, const double *epoch)

{
  // If EQUINOXa is currently undefined then set it from EPOCHa.
  if (undefined(*equinox)) {
    *equinox = *epoch;
  }

  return 0;
}


/*----------------------------------------------------------------------------
* Interpret VSOURCEa keywords.
*---------------------------------------------------------------------------*/

int wcspih_vsource(double *zsource, const double *vsource)

{
  const double c = 299792458.0;

  // If ZSOURCEa is currently undefined then set it from VSOURCEa.
  if (undefined(*zsource)) {
    // Convert relativistic Doppler velocity to redshift.
    double beta = *vsource/c;
    *zsource = (1.0 + beta)/sqrt(1.0 - beta*beta) - 1.0;
  }

  return 0;
}


/*----------------------------------------------------------------------------
* Check validity of a TIMEPIXR keyvalue.
*---------------------------------------------------------------------------*/

int wcspih_timepixr(double timepixr)

{
  return (timepixr < 0.0 || 1.0 < timepixr);
}


/*----------------------------------------------------------------------------
* Interpret special keywords encountered for each coordinate representation.
*---------------------------------------------------------------------------*/

int wcspih_final(
  int ndp[],
  int ndq[],
  int distran,
  double dsstmp[],
  char *wat[],
  int  *nwcs,
  struct wcsprm **wcs)

{
  for (int ialt = 0; ialt < *nwcs; ialt++) {
    // Interpret -TAB header keywords.
    int status;
    if ((status = wcstab(*wcs+ialt))) {
       wcsvfree(nwcs, wcs);
       return status;
    }

    if (ndp[ialt] && ndq[ialt]) {
      // Prior and sequent distortions co-exist in this representation;
      // ensure the latter gets DVERRa.
      (*wcs+ialt)->lin.disseq->totdis = (*wcs+ialt)->lin.dispre->totdis;
    }
  }

  // Translated distortion functions; apply only to the primary WCS.
  struct wcsprm *wcsp = *wcs;
  if (distran == SIP) {
    // SIP doesn't have alternates, nor axis mapping.
    struct disprm *disp = wcsp->lin.dispre;
    dpfill(disp->dp+1, "DP1", "OFFSET.1",  0, 1, 0, wcsp->crpix[0]);
    dpfill(disp->dp+2, "DP1", "OFFSET.2",  0, 1, 0, wcsp->crpix[1]);
    dpfill(disp->dp+4, "DP2", "OFFSET.1",  0, 1, 0, wcsp->crpix[0]);
    dpfill(disp->dp+5, "DP2", "OFFSET.2",  0, 1, 0, wcsp->crpix[1]);

  } else if (distran == DSS) {
    // DSS doesn't have alternates, nor axis mapping.  This translation
    // follows Paper IV, Sect. 5.2 using the same variable names.
    double CNPIX1 = dsstmp[0];
    double CNPIX2 = dsstmp[1];

    double Xc = dsstmp[2]/1000.0;
    double Yc = dsstmp[3]/1000.0;
    double Rx = dsstmp[4]/1000.0;
    double Ry = dsstmp[5]/1000.0;

    double A1 = dsstmp[14];
    double A2 = dsstmp[15];
    double A3 = dsstmp[16];
    double B1 = dsstmp[17];
    double B2 = dsstmp[18];
    double B3 = dsstmp[19];
    double S  = sqrt(fabs(A1*B1 - A2*B2));

    double X0 = (A2*B3 - A3*B1) / (A1*B1 - A2*B2);
    double Y0 = (A3*B2 - A1*B3) / (A1*B1 - A2*B2);

    wcsp->crpix[0] = (Xc - X0)/Rx - (CNPIX1 - 0.5);
    wcsp->crpix[1] = (Yc + Y0)/Ry - (CNPIX2 - 0.5);

    wcsp->pc[0] =  A1*Rx/S;
    wcsp->pc[1] = -A2*Ry/S;
    wcsp->pc[2] = -B2*Rx/S;
    wcsp->pc[3] =  B1*Ry/S;
    wcsp->altlin = 1;

    wcsp->cdelt[0] = -S/3600.0;
    wcsp->cdelt[1] =  S/3600.0;

    double *crval = wcsp->crval;
    crval[0] = (dsstmp[6]  + (dsstmp[7]  + dsstmp[8] /60.0)/60.0)*15.0;
    crval[1] =  dsstmp[10] + (dsstmp[11] + dsstmp[12]/60.0)/60.0;
    if (dsstmp[9] == -1.0) crval[1] *= -1.0;

    strncpy(wcsp->ctype[0], "RA---TAN", 72);
    strncpy(wcsp->ctype[1], "DEC--TAN", 72);

    snprintf(wcsp->wcsname, 72, "DSS PLATEID %.4s", (char *)(dsstmp+13));

    // Erase the approximate WCS provided in modern DSS headers.
    wcsp->cd[0] = 0.0;
    wcsp->cd[1] = 0.0;
    wcsp->cd[2] = 0.0;
    wcsp->cd[3] = 0.0;

  } else if (distran == WAT) {
    // TNX and ZPX don't have alternates, nor axis mapping.
    char *wp;
    int  omax, omin, wctrl[4];
    double wval;
    struct disprm *disp = wcsp->lin.disseq;

    // Disassemble the core dump stored in the WATi_m strings.
    int i, nterms = 0;
    for (i = 0; i < 2; i++) {
      char wtype[8];
      sscanf(wat[i], "wtype=%s", wtype);

      if (strcmp(wtype, "tnx") == 0) {
        strncpy(disp->dtype[i], "WAT-TNX", 72);
      } else if (strcmp(wtype, "zpx") == 0) {
        strncpy(disp->dtype[i], "WAT-ZPX", 72);
      } else {
        // Could contain "tan" or something else to be ignored.
        lindist(2, &(wcsp->lin), 0x0, 0);
        return 0;
      }

      // The PROJPn parameters are duplicated on each ZPX axis.
      if (i == 1 && strcmp(wtype, "zpx") == 0) {
        // Take those on the second (latitude) axis ignoring the other.
        // First we have to count them and allocate space in wcsprm.
        wp = wat[i];
	int npv;
        for (npv = 0; npv < 30; npv++) {
          if ((wp = strstr(wp, "projp")) == 0x0) break;
          wp += 5;
        }

        // Allocate space.
        if (npv) {
          wcsp->npvmax += npv;
          wcsp->pv = realloc(wcsp->pv, wcsp->npvmax*sizeof(struct pvcard));
          if (wcsp->pv == 0x0) {
            return WCSHDRERR_MEMORY;
          }

          wcsp->m_pv = wcsp->pv;
        }

        // Copy the values.
        wp = wat[i];
        for (int ipv = wcsp->npv; ipv < wcsp->npvmax; ipv++) {
          if ((wp = strstr(wp, "projp")) == 0x0) break;

          int m;
          sscanf(wp, "projp%d=%lf", &m, &wval);
          wcsp->pv[ipv].i = 2;
          wcsp->pv[ipv].m = m;
          wcsp->pv[ipv].value = wval;

          wp += 5;
        }

        wcsp->npv += npv;
      }

      // Read the control parameters.
      if ((wp = strchr(wat[i], '"')) == 0x0) {
        return WCSHDRERR_PARSER;
      }
      wp++;

      for (int m = 0; m < 4; m++) {
        sscanf(wp, "%d", wctrl+m);
        if ((wp = strchr(wp, ' ')) == 0x0) {
          return WCSHDRERR_PARSER;
        }
        wp++;
      }

      // How many coefficients are we expecting?
      omin = (wctrl[1] < wctrl[2]) ? wctrl[1] : wctrl[2];
      omax = (wctrl[1] < wctrl[2]) ? wctrl[2] : wctrl[1];
      if (wctrl[3] == 0) {
        // No cross terms.
        nterms += omin + omax;

      } else if (wctrl[3] == 1) {
        // Full cross terms.
        nterms += omin*omax;

      } else if (wctrl[3] == 2) {
        // Half cross terms.
        nterms += omin*omax - omin*(omin-1)/2;
      }
    }

    // Allocate memory for dpkeys.
    ndq[0] += 2*(1 + 1 + 4) + nterms;

    disp->ndpmax += ndq[0];
    disp->dp = realloc(disp->dp, disp->ndpmax*sizeof(struct dpkey));
    if (disp->dp == 0x0) {
      return WCSHDRERR_MEMORY;
    }

    disp->m_dp = disp->dp;


    // Populate dpkeys.
    int idp = disp->ndp;
    for (i = 0; i < 2; i++) {
      dpfill(disp->dp+(idp++), "DQ", "NAXES", i+1, 0, 2, 0.0);

      // Read the control parameters.
      if ((wp = strchr(wat[i], '"')) == 0x0) {
        return WCSHDRERR_PARSER;
      }
      wp++;

      for (int m = 0; m < 4; m++) {
        sscanf(wp, "%d", wctrl+m);
        if ((wp = strchr(wp, ' ')) == 0x0) {
          return WCSHDRERR_PARSER;
        }
        wp++;
      }

      // Polynomial type.
      char wpoly[12];
      dpfill(disp->dp+(idp++), "DQ", "WAT.POLY", i+1, 0, wctrl[0], 0.0);
      if (wctrl[0] == 1) {
        // Chebyshev polynomial.
        strncpy(wpoly, "CHBY", 12);
      } else if (wctrl[0] == 2) {
        // Legendre polynomial.
        strncpy(wpoly, "LEGR", 12);
      } else if (wctrl[0] == 3) {
        // Polynomial is the sum of monomials.
        strncpy(wpoly, "MONO", 12);
      } else {
        // Unknown code.
        strncpy(wpoly, "UNKN", 12);
      }

      // Read the scaling parameters.
      char field[40];
      for (int m = 0; m < 4; m++) {
        sscanf(wp, "%lf", &wval);
        snprintf(field, 40, "WAT.%c%s", (m<2)?'X':'Y', (m%2)?"MAX":"MIN");
        dpfill(disp->dp+(idp++), "DQ", field, i+1, 1, 0, wval);

        if ((wp = strchr(wp, ' ')) == 0x0) {
          return WCSHDRERR_PARSER;
        }
        wp++;
      }

      // Read the coefficients.
      for (int n = 0; n < wctrl[2]; n++) {
        for (int m = 0; m < wctrl[1]; m++) {
          if (wctrl[3] == 0) {
            if (m && n) continue;
          } else if (wctrl[3] == 2) {
            if (m+n > omax-1) continue;
          }

          sscanf(wp, "%lf", &wval);
          if (wval == 0.0) continue;

          snprintf(field, 40, "WAT.%s.%d_%d", wpoly, m, n);
          dpfill(disp->dp+(idp++), "DQ", field, i+1, 1, 0, wval);

          if ((wp = strchr(wp, ' ')) == 0x0) {
            return WCSHDRERR_PARSER;
          }
          wp++;
        }
      }
    }

    disp->ndp = idp;
  }

  return 0;
}
@


8.6
log
@WCSLIB 8.6
@
text
@d2 1
a2 1
  WCSLIB 8.6 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 8.5.1.2 2026/03/29 13:36:16 mcalabre Exp mcalabre $
d1595 1
a1595 1
	    sprintf(errmsg, "keyword looks very much like %s but isn't",
d1678 2
a1679 2
	  sprintf(errmsg, "%s keyword must use an underscore, not a dash",
	    keyname);
d1693 1
a1693 1
	    sprintf(errmsg,
d1724 2
a1725 2
	    sprintf(errmsg, "invalid alternate code, keyword resembles %s "
	      "but isn't", keyname);
d1806 2
a1807 2
	  sprintf(errmsg, "%s keyword must use an underscore, not a dash",
	    keyname);
d1958 1
a1958 1
	      sprintf(errmsg, "internal parser ERROR, bad data type: %d",
d2155 3
a2157 3
	          sprintf(keyword, "DP%d", i);
	          sprintf(strtmp, "SIP.%s.%d_%d", (sipflag==2)?"FWD":"REV",
	                  p, q);
d2172 1
a2172 1
	            strcpy((char *)vptr, strtmp);
d2182 2
a2183 2
	              sprintf(keyword, "DQ%d", i);
	              sprintf(strtmp, "DSS.AMD.%d", m);
d2195 1
a2195 1
	          strcpy((char *)vptr, strtmp);
d2284 1
a2284 1
	            strcpy(cptr, strtmp);
d2291 1
a2291 1
	              sprintf(keyword, "%.2s%d", keyname, i);
d2293 1
a2293 1
	              sprintf(keyword, "%.2s%d%c", keyname, i, a);
d2893 1
a2893 1
    sprintf(wcsp->wcsname, "DSS PLATEID %.4s", (char *)(dsstmp+13));
d3046 1
a3046 1
        sprintf(field, "WAT.%c%s", (m<2)?'X':'Y', (m%2)?"MAX":"MIN");
d3067 1
a3067 1
          sprintf(field, "WAT.%s.%d_%d", wpoly, m, n);
@


8.6.1.1
log
@WCSLIB 8.6 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.6 2026/03/29 13:53:56 mcalabre Exp $
@


8.6.1.2
log
@Replaced use of strcpy() with strncpy(), and sprintf() with snprintf().
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.6.1.1 2026/03/29 14:19:26 mcalabre Exp mcalabre $
d1595 1
a1595 1
	    snprintf(errmsg, 80, "keyword looks very much like %s but isn't",
d1678 2
a1679 2
	  snprintf(errmsg, 80,
	    "%s keyword must use an underscore, not a dash", keyname);
d1693 1
a1693 1
	    snprintf(errmsg, 80,
d1724 2
a1725 2
	    snprintf(errmsg, 80, "invalid alternate code, keyword resembles "
	      "%s but isn't", keyname);
d1806 2
a1807 2
	  snprintf(errmsg, 80,
	    "%s keyword must use an underscore, not a dash", keyname);
d1958 1
a1958 1
	      snprintf(errmsg, 80, "internal parser ERROR, bad data type: %d",
d2155 3
a2157 3
	          snprintf(keyword, 16, "DP%d", i);
	          snprintf(strtmp, 80, "SIP.%s.%d_%d",
	                  (sipflag==2)?"FWD":"REV", p, q);
d2172 1
a2172 1
	            strncpy((char *)vptr, strtmp, 8);
d2182 2
a2183 2
	              snprintf(keyword, 16, "DQ%d", i);
	              snprintf(strtmp, 80, "DSS.AMD.%d", m);
d2195 1
a2195 1
	          strncpy((char *)vptr, strtmp, 68);
d2284 1
a2284 1
	            strncpy(cptr, strtmp, 72);
d2291 1
a2291 1
	              snprintf(keyword, 16, "%.2s%d", keyname, i);
d2293 1
a2293 1
	              snprintf(keyword, 16, "%.2s%d%c", keyname, i, a);
d2893 1
a2893 1
    snprintf(wcsp->wcsname, 72, "DSS PLATEID %.4s", (char *)(dsstmp+13));
d3046 1
a3046 1
        snprintf(field, 40, "WAT.%c%s", (m<2)?'X':'Y', (m%2)?"MAX":"MIN");
d3067 1
a3067 1
          snprintf(field, 40, "WAT.%s.%d_%d", wpoly, m, n);
@


8.5
log
@WCSLIB 8.5
@
text
@d2 2
a3 2
  WCSLIB 8.5 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2025, Mark Calabretta
d21 2
a22 2
  http://www.atnf.csiro.au/people/Mark.Calabretta
  $Id: wcspih.l,v 8.4.1.3 2025/12/06 13:37:16 mcalabre Exp mcalabre $
@


8.5.1.1
log
@WCSLIB 8.5 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.5 2025/12/06 13:47:41 mcalabre Exp $
@


8.5.1.2
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2026, Mark Calabretta
d21 2
a22 2
  http://www.atnf.csiro.au/computing/software/wcs
  $Id: wcspih.l,v 8.5.1.1 2025/12/06 14:05:15 mcalabre Exp mcalabre $
@


8.4
log
@WCSLIB 8.4
@
text
@d2 2
a3 2
  WCSLIB 8.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2024, Mark Calabretta
d22 1
a22 1
  $Id: wcspih.l,v 8.3.1.1 2024/05/13 16:35:39 mcalabre Exp mcalabre $
d2031 13
a2043 8
	    // Copy the keyvalue minus the quotes.
	    strncpy(strtmp, yytext+1, yyleng-2);
	    strtmp[yyleng-2] = '\0';
	
	    // Strip off trailing blanks.
	    for (int jx = yyleng-3; jx >= 0; jx--) {
	      if (strtmp[jx] != ' ') {
	        break;
a2044 1
	      strtmp[jx] = '\0';
@


8.4.1.1
log
@WCSLIB 8.4 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.4 2024/10/28 13:56:16 mcalabre Exp $
@


8.4.1.2
log
@Quelled compiler warnings relating to strncpy().
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.4.1.1 2024/10/28 13:58:41 mcalabre Exp mcalabre $
d2031 8
a2038 13
	    strtmp[0] = '\0';
	    int nch = yyleng - 2;
	    if (0 < nch && nch < 80) {
	      // Copy the keyvalue minus the quotes.
	      strncpy(strtmp, yytext+1, nch);
	      strtmp[nch] = '\0';
	
	      // Strip off trailing blanks.
	      for (int jx = nch-1; jx >= 0; jx--) {
	        if (strtmp[jx] != ' ') {
	          break;
	        }
	        strtmp[jx] = '\0';
d2040 1
@


8.4.1.3
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2025, Mark Calabretta
d22 1
a22 1
  $Id: wcspih.l,v 8.4.1.2 2025/12/06 10:29:54 mcalabre Exp mcalabre $
@


8.3
log
@WCSLIB 8.3
@
text
@d2 1
a2 1
  WCSLIB 8.3 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 8.2.1.3 2024/04/02 14:01:58 mcalabre Exp mcalabre $
@


8.3.1.1
log
@WCSLIB 8.3 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.3 2024/05/13 16:33:00 mcalabre Exp $
@


8.2
log
@WCSLIB 8.2
@
text
@d2 2
a3 2
  WCSLIB 8.2 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2023, Mark Calabretta
d22 1
a22 1
  $Id: wcspih.l,v 8.1.1.1 2023/07/05 17:15:00 mcalabre Exp mcalabre $
d2031 2
a2032 4
	    // Copy the keyvalue, skipping the initial quote.
	    strncpy(strtmp, yytext+1, 80);
	
	    // Remove the terminating quote.
d2085 2
a2086 1
	  strncpy(strtmp, yytext, 80);
@


8.2.1.1
log
@WCSLIB 8.2 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.2 2023/11/16 10:00:29 mcalabre Exp $
@


8.2.1.2
log
@Quelled compiler warnings relating to strncpy with specified bound equal to
destination size.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.2.1.1 2023/11/16 10:05:57 mcalabre Exp mcalabre $
d2031 4
a2034 2
	    // Copy the keyvalue minus the quotes.
	    strncpy(strtmp, yytext+1, yyleng-2);
d2087 1
a2087 2
	  strncpy(strtmp, yytext, 72);
	  strtmp[72] = '\0';
@


8.2.1.3
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2024, Mark Calabretta
d22 1
a22 1
  $Id: wcspih.l,v 8.2.1.2 2023/12/20 13:13:25 mcalabre Exp mcalabre $
@


8.1
log
@WCSLIB 8.1
@
text
@d2 1
a2 1
  WCSLIB 8.1 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 8.0.1.1 2023/07/01 06:22:44 mcalabre Exp mcalabre $
@


8.1.1.1
log
@WCSLIB 8.1 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.1 2023/07/05 17:12:07 mcalabre Exp $
@


8.0
log
@WCSLIB 8.0
@
text
@d2 1
a2 1
  WCSLIB 8.0 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.13.1.5 2023/06/15 04:17:19 mcalabre Exp mcalabre $
@


8.0.1.1
log
@WCSLIB 8.0 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 8.0 2023/07/01 06:15:04 mcalabre Exp $
@


7.13
log
@WCSLIB 7.13
@
text
@d2 2
a3 2
  WCSLIB 7.13 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2022, Mark Calabretta
d22 1
a22 1
  $Id: wcspih.l,v 7.12.1.1 2022/09/09 05:00:36 mcalabre Exp mcalabre $
d1094 54
d2031 13
a2043 2
	    // Read the keyvalue.
	    strcpy(strtmp, yytext+1);
a2052 1
	        if (ix) strtmp[ix-1] = '\0';
d2087 1
a2087 1
	  strcpy(strtmp, yytext);
d2642 1
a2642 1
          strcpy(wcsp->wcsname, "DEFAULTS");
d2694 2
a2695 2
      strcpy((*wcs)->lin.dispre->dtype[0], "SIP");
      strcpy((*wcs)->lin.dispre->dtype[1], "SIP");
d2703 2
a2704 2
      strcpy((*wcs)->lin.disseq->dtype[0], "DSS");
      strcpy((*wcs)->lin.disseq->dtype[1], "DSS");
d2887 2
a2888 2
    strcpy(wcsp->ctype[0], "RA---TAN");
    strcpy(wcsp->ctype[1], "DEC--TAN");
d2912 1
a2912 1
        strcpy(disp->dtype[i], "WAT-TNX");
d2914 1
a2914 1
        strcpy(disp->dtype[i], "WAT-ZPX");
d3027 1
a3027 1
        strcpy(wpoly, "CHBY");
d3030 1
a3030 1
        strcpy(wpoly, "LEGR");
d3033 1
a3033 1
        strcpy(wpoly, "MONO");
d3036 1
a3036 1
        strcpy(wpoly, "UNKN");
@


7.13.1.1
log
@WCSLIB 7.13 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.13 2022/10/07 03:43:35 mcalabre Exp $
@


7.13.1.2
log
@Support planetary keywords A_RADIUS, B_RADIUS, C_RADIUS, PLON_OBS, PLAT_OBS,
and PDIS_OBS in auxprm.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.13.1.1 2022/10/07 03:45:47 mcalabre Exp mcalabre $
a1090 54
	  BEGIN(CCCCCCCC);
	}

^A_RADIUS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.a_radius);
	
	  keyname = "A_RADIUS";
	  BEGIN(CCCCCCCC);
	}

^B_RADIUS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.b_radius);
	
	  keyname = "B_RADIUS";
	  BEGIN(CCCCCCCC);
	}

^C_RADIUS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.c_radius);
	
	  keyname = "C_RADIUS";
	  BEGIN(CCCCCCCC);
	}

^PLON_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.plon_obs);
	
	  keyname = "PLON_OBS";
	  BEGIN(CCCCCCCC);
	}

^PLAT_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.plat_obs);
	
	  keyname = "PLAT_OBS";
	  BEGIN(CCCCCCCC);
	}

^PDIS_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.pdis_obs);
	
	  keyname = "PDIS_OBS";
@


7.13.1.3
log
@In the <STRING_VAL>{STRING} rule, strip trailing blanks from string
keyvalues.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.13.1.2 2023/06/03 08:24:14 mcalabre Exp mcalabre $
d2031 2
a2032 13
	    // Copy the keyvalue, skipping the initial quote.
	    strncpy(strtmp, yytext+1, 80);
	
	    // Remove the terminating quote.
	    strtmp[yyleng-2] = '\0';
	
	    // Strip off trailing blanks.
	    for (int jx = yyleng-3; jx >= 0; jx--) {
	      if (strtmp[jx] != ' ') {
	        break;
	      }
	      strtmp[jx] = '\0';
	    }
d2042 1
d2077 1
a2077 1
	  strncpy(strtmp, yytext, 80);
d2632 1
a2632 1
          strncpy(wcsp->wcsname, "DEFAULTS", 72);
d2684 2
a2685 2
      strncpy((*wcs)->lin.dispre->dtype[0], "SIP", 72);
      strncpy((*wcs)->lin.dispre->dtype[1], "SIP", 72);
d2693 2
a2694 2
      strncpy((*wcs)->lin.disseq->dtype[0], "DSS", 72);
      strncpy((*wcs)->lin.disseq->dtype[1], "DSS", 72);
d2877 2
a2878 2
    strncpy(wcsp->ctype[0], "RA---TAN", 72);
    strncpy(wcsp->ctype[1], "DEC--TAN", 72);
d2902 1
a2902 1
        strncpy(disp->dtype[i], "WAT-TNX", 72);
d2904 1
a2904 1
        strncpy(disp->dtype[i], "WAT-ZPX", 72);
d3017 1
a3017 1
        strncpy(wpoly, "CHBY", 12);
d3020 1
a3020 1
        strncpy(wpoly, "LEGR", 12);
d3023 1
a3023 1
        strncpy(wpoly, "MONO", 12);
d3026 1
a3026 1
        strncpy(wpoly, "UNKN", 12);
@


7.13.1.4
log
@(PLON_OBS, PLAT_OBS, PDIS_OBS) -> (BLON_OBS, BLAT_OBS, BDIS_OBS).
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.13.1.3 2023/06/03 14:21:54 mcalabre Exp mcalabre $
d1121 1
a1121 1
^BLON_OBS {
d1124 1
a1124 1
	  vptr    = &(auxtem.blon_obs);
d1126 1
a1126 1
	  keyname = "BLON_OBS";
d1130 1
a1130 1
^BLAT_OBS {
d1133 1
a1133 1
	  vptr    = &(auxtem.blat_obs);
d1135 1
a1135 1
	  keyname = "BLAT_OBS";
d1139 1
a1139 1
^BDIS_OBS {
d1142 1
a1142 1
	  vptr    = &(auxtem.bdis_obs);
d1144 1
a1144 1
	  keyname = "BDIS_OBS";
@


7.13.1.5
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2023, Mark Calabretta
d22 1
a22 1
  $Id: wcspih.l,v 7.13.1.4 2023/06/15 03:58:10 mcalabre Exp mcalabre $
@


7.12
log
@WCSLIB 7.12
@
text
@d2 1
a2 1
  WCSLIB 7.12 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.11.1.1 2022/04/26 06:15:32 mcalabre Exp mcalabre $
@


7.12.1.1
log
@WCSLIB 7.12 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.12 2022/09/09 04:57:58 mcalabre Exp $
@


7.11
log
@WCSLIB 7.11
@
text
@d2 1
a2 1
  WCSLIB 7.11 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.10.1.1 2022/04/23 14:26:54 mcalabre Exp mcalabre $
@


7.11.1.1
log
@WCSLIB 7.11 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.11 2022/04/26 06:13:52 mcalabre Exp $
@


7.10
log
@WCSLIB 7.10
@
text
@d2 1
a2 1
  WCSLIB 7.10 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.9.1.1 2022/03/25 15:16:40 mcalabre Exp mcalabre $
@


7.10.1.1
log
@WCSLIB 7.10 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.10 2022/04/23 14:25:15 mcalabre Exp $
@


7.9
log
@WCSLIB 7.9
@
text
@d2 1
a2 1
  WCSLIB 7.9 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.8.1.1 2022/03/25 06:14:14 mcalabre Exp mcalabre $
@


7.9.1.1
log
@WCSLIB 7.9 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.9 2022/03/25 15:14:48 mcalabre Exp $
@


7.8
log
@WCSLIB 7.8
@
text
@d2 1
a2 1
  WCSLIB 7.8 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.7.1.2 2022/03/25 06:05:59 mcalabre Exp mcalabre $
@


7.8.1.1
log
@WCSLIB 7.8 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.8 2022/03/25 06:11:49 mcalabre Exp $
@


7.7
log
@WCSLIB 7.7
@
text
@d2 2
a3 2
  WCSLIB 7.7 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2021, Mark Calabretta
d22 1
a22 1
  $Id: wcspih.l,v 7.6.1.1 2021/04/13 13:00:35 mcalabre Exp mcalabre $
@


7.7.1.1
log
@WCSLIB 7.7 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.7 2021/07/12 06:36:49 mcalabre Exp $
@


7.7.1.2
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2022, Mark Calabretta
d22 1
a22 1
  $Id: wcspih.l,v 7.7.1.1 2021/07/12 06:38:27 mcalabre Exp mcalabre $
@


7.6
log
@WCSLIB 7.6
@
text
@d2 1
a2 1
  WCSLIB 7.6 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.5.1.1 2021/03/20 05:56:42 mcalabre Exp mcalabre $
@


7.6.1.1
log
@WCSLIB 7.6 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.6 2021/04/13 12:57:01 mcalabre Exp $
@


7.5
log
@WCSLIB 7.5
@
text
@d2 1
a2 1
  WCSLIB 7.5 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.4.1.3 2021/02/25 14:17:41 mcalabre Exp mcalabre $
@


7.5.1.1
log
@WCSLIB 7.5 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.5 2021/03/20 05:54:58 mcalabre Exp $
@


7.4
log
@WCSLIB 7.4
@
text
@d2 1
a2 1
  WCSLIB 7.4 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: wcspih.l,v 7.3.1.4 2021/01/28 12:29:30 mcalabre Exp mcalabre $
d73 1
d138 9
a146 30
static int wcspih_scanner(char *header, int nkeyrec, int relax, int ctrl,
                          int *nreject, int *nwcs, struct wcsprm **wcs,
                          yyscan_t yyscanner);

//----------------------------------------------------------------------------

int wcspih(
  char *header,
  int nkeyrec,
  int relax,
  int ctrl,
  int *nreject,
  int *nwcs,
  struct wcsprm **wcs)

{
  int status;
  yyscan_t yyscanner;
  int yylex_init(yyscan_t *yyscanner);
  int yylex_destroy(yyscan_t yyscanner);

  yylex_init(&yyscanner);
  status = wcspih_scanner(header, nkeyrec, relax, ctrl, nreject, nwcs, wcs,
                          yyscanner);
  yylex_destroy(yyscanner);

  return status;
}

//----------------------------------------------------------------------------
d153 2
a154 2
	  if (wcspih_nkeyrec) { \
	    strncpy(inbuff, wcspih_hdr, 80); \
d156 2
a157 2
	    wcspih_hdr += 80; \
	    wcspih_nkeyrec--; \
d164 2
a165 3
// These global variables are required by YY_INPUT.
static char *wcspih_hdr;
static int  wcspih_nkeyrec;
d168 1
a184 4
// Used in preempting the call to exit() by yy_fatal_error().
jmp_buf wcspih_abort_jmp_env;
#define exit(status) longjmp(wcspih_abort_jmp_env, status)

d188 4
a191 11
	// Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma.
	char a;
	int  i, j, m, p, q;
	
	char *cptr, *errmsg, errtxt[80], *hptr, *keep, *keyname, *keyrec,
	     keyword[16], strtmp[80], *wat[2], *watstr;
	int  altlin, alts[27], auxprm, distran, distype, dpq[27], dssflag,
	     gotone, ialt, inttmp, ipass, ipx, ix, jx, naux, naxis,
	     ndp[27], ndq[27], nother, *npptr, nps[27], npass, npv[27],
	     nvalid, rectype, sipflag, status, valtype, watflag, watn;
	ptrdiff_t voff;
d193 3
a195 6
	void *vptr, *wptr;
	struct auxprm *auxp, auxtem;
	struct disprm *disp, distem;
	struct wcsprm *wcsp, wcstem;
	int (*chekval)(double);
	int (*special)(double *, const double *);
d197 2
a198 2
	naxis = 0;
	for (ialt = 0; ialt < 27; ialt++) {
a206 4
	// Parameters used to implement YY_INPUT.
	wcspih_hdr = header;
	wcspih_nkeyrec = nkeyrec;
	
d208 3
a210 3
	keyrec = header;
	hptr = header;
	keep = 0x0;
d214 2
a215 2
	nvalid = 0;
	nother = 0;
d220 5
a224 4
	// Keyword parameters.
	i = j = 0;
	m = 0;
	a = ' ';
d227 3
a229 3
	valtype = -1;
	distype =  0;
	vptr    = 0x0;
d232 11
a242 11
	altlin  = 0;
	npptr   = 0x0;
	chekval = 0x0;
	special = 0x0;
	auxprm  = 0;
	naux    = 0;
	distran = 0;
	sipflag = 0;
	dssflag = 0;
	watflag = 0;
	watn    = 0;
d249 6
a254 2
	ipass = 1;
	npass = 2;
d257 2
a258 2
	if (setjmp(wcspih_abort_jmp_env)) {
	  return 3;
d1477 2
a1478 2
	  if (wcspih_nkeyrec) {
	    wcspih_nkeyrec = 0;
d1981 2
a1982 2
	    ix = 0;
	    for (jx = 0; jx < 72; jx++) {
d2070 2
a2071 2
	    gotone = 0;
	    for (ialt = 0; ialt < *nwcs; ialt++) {
d2083 2
a2084 2
	          disp = (*wcs)->lin.dispre;
	          ipx = (disp->ndp)++;
d2087 1
d2110 2
a2111 2
	              disp = (*wcs)->lin.disseq;
	              ipx = (disp->ndp)++;
d2114 1
d2132 4
a2135 1
	          wcsp = *wcs + ialt;
d2138 1
a2138 1
	            auxp = wcsp->aux;
d2166 1
a2166 1
	              ipx = (wcsp->npv)++;
d2203 1
a2203 1
	              ipx = (wcsp->nps)++;
d2216 1
a2216 1
	            cptr = (char *)wptr;
d2220 1
a2220 1
	            ipx = (disp->ndp)++;
d2222 1
d2243 1
a2243 1
	            "recognised WCS convention.\n", keyrec, nvalid);
d2350 1
d2375 2
a2376 2
	    wcspih_hdr = header;
	    wcspih_nkeyrec = nkeyrec;
d2425 29
a2471 2
  int ialt, *ip;

d2476 1
a2476 1
  ialt = 0;
d2481 1
a2481 1
  ip = alts + ialt;
d2525 1
a2525 3
  int ialt, defaults, ndis, ndpmax, npsmax, npvmax, status = 0;
  struct wcsprm *wcsp;
  struct disprm *dis;
d2529 1
a2529 1
  for (ialt = 0; ialt < 27; ialt++) {
d2533 1
d2547 1
a2547 1
    ndis = 0;
d2559 1
a2559 1
    wcsp = *wcs;
d2561 1
a2561 1
    for (ialt = 0; ialt < 27; ialt++) {
d2564 2
a2565 2
        npvmax = npv[ialt];
        npsmax = nps[ialt];
d2589 1
d2591 1
a2591 1
          if ((dis = calloc(1, sizeof(struct disprm))) == 0x0) {
d2597 3
a2599 3
          ndpmax = ndp[ialt];
          dis->flag = -1;
          lindist(1, &(wcsp->lin), dis, ndpmax);
d2603 1
a2603 1
          if ((dis = calloc(1, sizeof(struct disprm))) == 0x0) {
d2609 3
a2611 3
          ndpmax = ndq[ialt];
          dis->flag = -1;
          lindist(2, &(wcsp->lin), dis, ndpmax);
d2721 1
a2721 1
  double beta, c = 299792458.0;
d2726 1
a2726 1
    beta = *vsource/c;
d2759 1
a2759 8
  char   field[32], *wp, wpoly[12], wtype[8];
  int    i, ialt, idp, ipv, m, npv, n, nterms, omax, omin, status, wctrl[4];
  double A1, A2, A3, B1, B2, B3, CNPIX1, CNPIX2, *crval, Rx, Ry, S, wval,
         X0, Y0, Xc, Yc;
  struct disprm *disp;
  struct wcsprm *wcsp;

  for (ialt = 0; ialt < *nwcs; ialt++) {
d2761 1
d2775 1
a2775 1
  wcsp = *wcs;
d2778 1
a2778 1
    disp = wcsp->lin.dispre;
d2787 2
a2788 2
    CNPIX1 = dsstmp[0];
    CNPIX2 = dsstmp[1];
d2790 12
a2801 12
    Xc = dsstmp[2]/1000.0;
    Yc = dsstmp[3]/1000.0;
    Rx = dsstmp[4]/1000.0;
    Ry = dsstmp[5]/1000.0;

    A1 = dsstmp[14];
    A2 = dsstmp[15];
    A3 = dsstmp[16];
    B1 = dsstmp[17];
    B2 = dsstmp[18];
    B3 = dsstmp[19];
    S  = sqrt(fabs(A1*B1 - A2*B2));
d2803 2
a2804 2
    X0 = (A2*B3 - A3*B1) / (A1*B1 - A2*B2);
    Y0 = (A3*B2 - A1*B3) / (A1*B1 - A2*B2);
d2818 1
a2818 1
    crval = wcsp->crval;
d2836 4
a2839 1
    disp = wcsp->lin.disseq;
d2842 1
a2842 1
    nterms = 0;
d2844 1
d2861 2
a2862 1
        wp  = wat[i];
d2881 1
a2881 1
        for (ipv = wcsp->npv; ipv < wcsp->npvmax; ipv++) {
d2884 1
d2902 1
a2902 1
      for (m = 0; m < 4; m++) {
d2940 1
a2940 1
    idp = disp->ndp;
d2950 1
a2950 1
      for (m = 0; m < 4; m++) {
d2959 1
d2976 2
a2977 1
      for (m = 0; m < 4; m++) {
d2989 2
a2990 2
      for (n = 0; n < wctrl[2]; n++) {
        for (m = 0; m < wctrl[1]; m++) {
@


7.4.1.1
log
@WCSLIB 7.4 development branch.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.4 2021/01/31 02:24:51 mcalabre Exp $
@


7.4.1.2
log
@Use of global variables (wcspih_hdr, wcspih_nkeyrec, and wcspih_abort_jmp_env)
made the code thread-unsafe.  Modified to use the yyextra mechanism instead.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.4.1.1 2021/01/31 02:26:24 mcalabre Exp mcalabre $
a72 1
%option extra-type="struct wcspih_extra *"
d137 30
a166 9
// User data associated with yyscanner.
struct wcspih_extra {
  // Values passed to YY_INPUT.
  char *hdr;
  int  nkeyrec;

  // Used in preempting the call to exit() by yy_fatal_error().
  jmp_buf abort_jmp_env;
};
d173 2
a174 2
	  if (yyextra->nkeyrec) { \
	    strncpy(inbuff, yyextra->hdr, 80); \
d176 2
a177 2
	    yyextra->hdr += 80; \
	    yyextra->nkeyrec--; \
d184 3
a186 2
// Preempt the call to exit() by yy_fatal_error().
#define exit(status) longjmp(yyextra->abort_jmp_env, status);
a188 1
static YY_DECL;
d205 4
d241 4
a288 4
	// User data associated with yyscanner.
	yyextra->hdr = header;
	yyextra->nkeyrec = nkeyrec;
	
d290 2
a291 2
	if (setjmp(yyextra->abort_jmp_env)) {
	  return WCSHDRERR_PARSER;
d1510 2
a1511 2
	  if (yyextra->nkeyrec) {
	    yyextra->nkeyrec = 0;
d2401 2
a2402 2
	    yyextra->hdr = header;
	    yyextra->nkeyrec = nkeyrec;
a2448 29

/*----------------------------------------------------------------------------
* External interface to the scanner.
*---------------------------------------------------------------------------*/

int wcspih(
  char *header,
  int nkeyrec,
  int relax,
  int ctrl,
  int *nreject,
  int *nwcs,
  struct wcsprm **wcs)

{
  // Function prototypes.
  int yylex_init_extra(YY_EXTRA_TYPE extra, yyscan_t *yyscanner);
  int yylex_destroy(yyscan_t yyscanner);

  struct wcspih_extra extra;
  yyscan_t yyscanner;
  yylex_init_extra(&extra, &yyscanner);
  int status = wcspih_scanner(header, nkeyrec, relax, ctrl, nreject, nwcs,
                              wcs, yyscanner);
  yylex_destroy(yyscanner);

  return status;
}

@


7.4.1.3
log
@Converted to C99-style intermingled variable declarations.
@
text
@d22 1
a22 1
  $Id: wcspih.l,v 7.4.1.2 2021/02/25 13:43:44 mcalabre Exp mcalabre $
d188 11
a198 4
	int  p, q;
	char *errmsg, errtxt[80], *keyname, strtmp[80], *wat[2], *watstr;
	int  alts[27], dpq[27], inttmp, ndp[27], ndq[27], nps[27], npv[27],
	     rectype;
d200 6
a205 3
	struct auxprm auxtem;
	struct disprm distem;
	struct wcsprm wcstem;
d207 2
a208 2
	int naxis = 0;
	for (int ialt = 0; ialt < 27; ialt++) {
d218 3
a220 3
	char *keyrec = header;
	char *hptr = header;
	char *keep = 0x0;
d224 2
a225 2
	int nvalid = 0;
	int nother = 0;
d230 4
a233 5
	// Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma.
	int i = 0;
	int j = 0;
	int m = 0;
	char a = ' ';
d236 3
a238 3
	int valtype = -1;
	int distype =  0;
	void *vptr  = 0x0;
d241 11
a251 11
	int altlin  = 0;
	int *npptr  = 0x0;
	int (*chekval)(double) = 0x0;
	int (*special)(double *, const double *) = 0x0;
	int auxprm  = 0;
	int naux    = 0;
	int distran = 0;
	int sipflag = 0;
	int dssflag = 0;
	int watflag = 0;
	int watn    = 0;
d258 2
a259 2
	int ipass = 1;
	int npass = 2;
d1990 2
a1991 2
	    int ix = 0;
	    for (int jx = 0; jx < 72; jx++) {
d2079 2
a2080 2
	    int gotone = 0;
	    for (int ialt = 0; ialt < *nwcs; ialt++) {
d2092 2
a2093 2
	          struct disprm *disp = (*wcs)->lin.dispre;
	          int ipx = (disp->ndp)++;
a2095 1
		  char keyword[16];
d2118 2
a2119 2
	              struct disprm *disp = (*wcs)->lin.disseq;
	              int ipx = (disp->ndp)++;
a2121 1
		      char keyword[16];
d2139 1
a2139 4
	          struct wcsprm *wcsp = *wcs + ialt;
		  struct disprm *disp;
	          void *wptr;
	          ptrdiff_t voff;
d2142 1
a2142 1
	            struct auxprm *auxp = wcsp->aux;
d2170 1
a2170 1
	              int ipx = (wcsp->npv)++;
d2207 1
a2207 1
	              int ipx = (wcsp->nps)++;
d2220 1
a2220 1
	            char *cptr = (char *)wptr;
d2224 1
a2224 1
	            int ipx = (disp->ndp)++;
a2225 1
		    char keyword[16];
d2246 1
a2246 1
	            "recognized WCS convention.\n", keyrec, nvalid);
a2352 1
	  int status;
d2474 2
d2480 1
a2480 1
  int ialt = 0;
d2485 1
a2485 1
  int *ip = alts + ialt;
d2529 3
a2531 1
  int status = 0;
d2535 1
a2535 1
  for (int ialt = 0; ialt < 27; ialt++) {
a2538 1
  int defaults;
d2552 1
a2552 1
    int ndis = 0;
d2564 1
a2564 1
    struct wcsprm *wcsp = *wcs;
d2566 1
a2566 1
    for (int ialt = 0; ialt < 27; ialt++) {
d2569 2
a2570 2
        int npvmax = npv[ialt];
        int npsmax = nps[ialt];
a2593 1
        struct disprm *disp;
d2595 1
a2595 1
          if ((disp = calloc(1, sizeof(struct disprm))) == 0x0) {
d2601 3
a2603 3
          int ndpmax = ndp[ialt];
          disp->flag = -1;
          lindist(1, &(wcsp->lin), disp, ndpmax);
d2607 1
a2607 1
          if ((disp = calloc(1, sizeof(struct disprm))) == 0x0) {
d2613 3
a2615 3
          int ndpmax = ndq[ialt];
          disp->flag = -1;
          lindist(2, &(wcsp->lin), disp, ndpmax);
d2725 1
a2725 1
  const double c = 299792458.0;
d2730 1
a2730 1
    double beta = *vsource/c;
d2763 8
a2770 1
  for (int ialt = 0; ialt < *nwcs; ialt++) {
a2771 1
    int status;
d2785 1
a2785 1
  struct wcsprm *wcsp = *wcs;
d2788 1
a2788 1
    struct disprm *disp = wcsp->lin.dispre;
d2797 2
a2798 2
    double CNPIX1 = dsstmp[0];
    double CNPIX2 = dsstmp[1];
d2800 12
a2811 12
    double Xc = dsstmp[2]/1000.0;
    double Yc = dsstmp[3]/1000.0;
    double Rx = dsstmp[4]/1000.0;
    double Ry = dsstmp[5]/1000.0;

    double A1 = dsstmp[14];
    double A2 = dsstmp[15];
    double A3 = dsstmp[16];
    double B1 = dsstmp[17];
    double B2 = dsstmp[18];
    double B3 = dsstmp[19];
    double S  = sqrt(fabs(A1*B1 - A2*B2));
d2813 2
a2814 2
    double X0 = (A2*B3 - A3*B1) / (A1*B1 - A2*B2);
    double Y0 = (A3*B2 - A1*B3) / (A1*B1 - A2*B2);
d2828 1
a2828 1
    double *crval = wcsp->crval;
d2846 1
a2846 4
    char *wp;
    int  omax, omin, wctrl[4];
    double wval;
    struct disprm *disp = wcsp->lin.disseq;
d2849 1
a2849 1
    int i, nterms = 0;
a2850 1
      char wtype[8];
d2867 1
a2867 2
        wp = wat[i];
	int npv;
d2886 1
a2886 1
        for (int ipv = wcsp->npv; ipv < wcsp->npvmax; ipv++) {
a2888 1
          int m;
d2906 1
a2906 1
      for (int m = 0; m < 4; m++) {
d2944 1
a2944 1
    int idp = disp->ndp;
d2954 1
a2954 1
      for (int m = 0; m < 4; m++) {
a2962 1
      char wpoly[12];
d2979 1
a2979 2
      char field[40];
      for (int m = 0; m < 4; m++) {
d2991 2
a2992 2
      for (int n = 0; n < wctrl[2]; n++) {
        for (int m = 0; m < wctrl[1]; m++) {
@


7.3
log
@WCSLIB 7.3
@
text
@d2 2
a3 3

  WCSLIB 7.3 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2020, Mark Calabretta
a19 2
  Direct correspondence concerning WCSLIB to mark@@calabretta.id.au

d22 1
a22 1
  $Id: wcspih.l,v 7.2.1.2 2020/06/02 08:52:36 mcalabre Exp mcalabre $
d141 1
a141 1
/*--------------------------------------------------------------------------*/
d166 1
a166 1
/*--------------------------------------------------------------------------*/
d184 1
a184 1
/* These global variables are required by YY_INPUT. */
d188 1
a188 1
/* Internal helper functions. */
d205 1
a205 1
/* Used in preempting the call to exit() by yy_fatal_error(). */
d212 1
a212 1
	/* Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma. */
d241 1
a241 1
	/* Parameters used to implement YY_INPUT. */
d245 1
a245 1
	/* Our handle on the input stream. */
d250 1
a250 1
	/* For keeping tallies of keywords found. */
d255 1
a255 1
	/* If strict, then also reject. */
d258 1
a258 1
	/* Keyword parameters. */
d263 1
a263 1
	/* For decoding the keyvalue. */
d268 1
a268 1
	/* For keywords that require special handling. */
d281 1
a281 1
	/* The data structures produced. */
d285 1
a285 1
	/* Control variables. */
d289 1
a289 1
	/* Return here via longjmp() invoked by yy_fatal_error(). */
d627 1
a627 1
	    /* Actually integer, but treated as float. */
d683 1
a683 1
	    /* Actually integer, but treated as float. */
d1193 1
a1193 1
	  /* SIP: axis 1 polynomial degree (not stored). */
d1206 1
a1206 1
	  /* SIP: axis 2 polynomial degree (not stored). */
d1219 1
a1219 1
	  /* SIP: axis 1 inverse polynomial degree (not stored). */
d1232 1
a1232 1
	  /* SIP: axis 2 inverse polynomial degree (not stored). */
d1245 1
a1245 1
	  /* SIP: axis 1 maximum distortion. */
d1258 1
a1258 1
	  /* SIP: axis 2 maximum distortion. */
d1271 1
a1271 1
	  /* SIP: axis 1 polynomial coefficient. */
d1280 1
a1280 1
	  /* SIP: axis 2 polynomial coefficient. */
d1289 1
a1289 1
	  /* SIP: axis 1 inverse polynomial coefficient. */
d1298 1
a1298 1
	  /* SIP: axis 2 inverse polynomial coefficient. */
d1307 1
a1307 1
	  /* DSS: LLH corner pixel coordinate 1. */
d1319 1
a1319 1
	  /* DSS: LLH corner pixel coordinate 2. */
d1331 1
a1331 1
	  /* DSS: plate centre x-coordinate in micron. */
d1343 1
a1343 1
	  /* DSS: plate centre y-coordinate in micron. */
d1355 1
a1355 1
	  /* DSS: pixel x-dimension in micron. */
d1367 1
a1367 1
	  /* DSS: pixel y-dimension in micron. */
d1379 1
a1379 1
	  /* DSS: plate centre, right ascension - hours. */
d1391 1
a1391 1
	  /* DSS: plate centre, right ascension - minutes. */
d1403 1
a1403 1
	  /* DSS: plate centre, right ascension - seconds. */
d1415 1
a1415 1
	  /* DSS: plate centre, declination - sign. */
d1427 1
a1427 1
	  /* DSS: plate centre, declination - degrees. */
d1439 1
a1439 1
	  /* DSS: plate centre, declination - arcmin. */
d1451 1
a1451 1
	  /* DSS: plate centre, declination - arcsec. */
d1463 1
a1463 1
	  /* DSS: plate identification (insufficient to trigger DSS). */
d1475 1
a1475 1
	  /* DSS: axis 1 polynomial coefficient. */
d1484 1
a1484 1
	  /* DSS: axis 2 polynomial coefficient. */
d1493 1
a1493 1
	  /* TNX or ZPX: string-encoded data array. */
d1539 1
a1539 1
	    /* Violates the basic FITS standard. */
d1545 1
a1545 1
	    /* Pretend we don't recognize it. */
d1559 2
a1560 2
	  /* Anything that has fallen through to this point must contain */
	  /* an invalid axis number. */
d1566 1
a1566 1
	  /* Let it go. */
d1572 1
a1572 1
	    /* Looks too much like a FITS WCS keyword not to flag it. */
d1579 1
a1579 1
	    /* Let it go. */
d1625 1
a1625 1
	    /* Pretend we don't recognize it. */
d1640 2
a1641 2
	  /* Anything that has fallen through to this point must contain */
	  /* an invalid axis number. */
d1663 1
a1663 1
	  /* This covers the defunct forms CD00i00j and PC00i00j. */
d1678 1
a1678 1
	    /* Pretend we don't recognize it. */
d1701 1
a1701 1
	    /* Looks too much like a FITS WCS keyword not to flag it. */
d1708 1
a1708 1
	    /* Pretend we don't recognize it. */
d1753 1
a1753 1
	    /* Pretend we don't recognize it. */
d1768 2
a1769 2
	  /* Anything that has fallen through to this point must contain */
	  /* an invalid axis number. */
d1813 1
a1813 1
	    /* Pretend we don't recognize it. */
d1856 1
a1856 1
	  /* SIP keywords. */
d1876 1
a1876 1
	  /* DSS keywords. */
d1894 1
a1894 1
	  /* Special handling for this iconic DSS keyword. */
d1896 1
a1896 1
	    /* Look for a minus sign. */
d1909 1
a1909 1
	  /* Do checks on i, j & m. */
d1920 1
a1920 1
	      /* Pretend we don't recognize it. */
d1954 1
a1954 1
	    /* Read the keyvalue. */
d1971 1
a1971 1
	    /* Read the keyvalue. */
d1993 1
a1993 1
	    /* Read the keyvalue as integer and fractional parts. */
d2010 1
a2010 1
	    /* Read the keyvalue. */
d2013 1
a2013 1
	    /* Squeeze out repeated quotes. */
d2097 1
a2097 1
	    /* Do first-pass bookkeeping. */
d2102 1
a2102 1
	    /* Store the value now that the keyrecord has been validated. */
d2105 2
a2106 2
	      /* The loop here is for keywords that apply */
	      /* to every alternate; these have a == 0. */
d2115 1
a2115 1
	          /* Translate a SIP keyword into DPja. */
d2119 1
a2119 1
	          /* SIP doesn't have alternates. */
d2130 1
a2130 1
	          /* All DSS keywords require special handling. */
d2132 1
a2132 1
	            /* Temporary parameter for DSS used by wcspih_final(). */
d2136 1
a2136 1
	            /* Temporary parameter for DSS used by wcspih_final(). */
d2140 1
a2140 1
	            /* Translate a DSS keyword into DQia. */
d2145 1
a2145 1
	              /* DSS doesn't have alternates. */
d2150 1
a2150 1
	              /* Also required by wcspih_final(). */
d2158 1
a2158 1
	          /* String array for TNX and ZPX used by wcspih_final(). */
d2162 1
a2162 1
	          /* An "ordinary" keyword. */
d2165 1
a2165 1
	            /* Additional auxiliary parameter. */
d2171 1
a2171 1
	            /* Distortion parameter of some kind. */
d2173 1
a2173 1
	              /* Prior distortion. */
d2176 1
a2176 1
	              /* Sequent distortion. */
d2183 1
a2183 1
	            /* A parameter that lives directly in wcsprm. */
d2192 1
a2192 1
	            /* Apply keyword parameterization. */
d2213 1
a2213 1
	            /* Flag presence of PCi_ja, or CDi_ja and/or CROTAia. */
d2220 1
a2220 1
	            /* Split MJDREF and JDREF into integer and fraction.*/
d2229 1
a2229 1
	            /* Apply keyword parameterization. */
d2312 1
a2312 1
	      /* Preserve discards. */
d2329 1
a2329 1
	      /* Preserve rejects. */
d2351 1
a2351 1
	  /* Throw away the rest of the line and reset for the next one. */
d2376 1
a2376 1
	  /* End-of-input. */
d2467 2
a2468 2
  /* On the first pass alts[] is used to determine the number of axes */
  /* for each of the 27 possible alternate coordinate descriptions.   */
d2486 1
a2486 1
  /* i or j can be greater than naxis. */
d2495 1
a2495 1
  /* Type of distortions present. */
d2498 1
a2498 1
  /* Count PVi_ma, PSi_ma, DPja, or DQia keywords. */
d2528 1
a2528 1
  /* Find the number of coordinate descriptions. */
d2535 2
a2536 2
    /* NAXIS is non-zero but there were no WCS keywords with an alternate
       version code; create a default WCS with blank alternate version. */
d2542 1
a2542 1
    /* Allocate memory for the required number of wcsprm structs. */
d2549 2
a2550 2
      /* DPja.NAXES and DPja.OFFSET.j to be added for SIP (see below and
         wcspih_final()). */
d2554 1
a2554 1
      /* DPja.NAXES to be added for DSS (see below and wcspih_final()). */
d2558 1
a2558 1
    /* Initialize each wcsprm struct. */
d2571 1
a2571 1
        /* Record the alternate version code. */
d2576 1
a2576 1
        /* Record in wcsname whether this is a default description. */
d2581 1
a2581 1
        /* Any additional auxiliary keywords present? */
d2588 1
a2588 1
        /* Any distortions present? */
d2594 1
a2594 1
          /* Attach it to linprm.  Also inits it. */
d2606 1
a2606 1
          /* Attach it to linprm.  Also inits it. */
d2613 1
a2613 1
        /* On the second pass alts[] indexes the array of wcsprm structs. */
d2619 1
a2619 1
        /* Signal that there is no wcsprm for this alt. */
d2625 3
a2627 3
    /* Translated distortion?  Neither SIP nor DSS have alternates, so the */
    /* presence of keywords for either (not both together), as flagged by  */
    /* distran, necessarily refers to the primary representation.          */
d2632 1
a2632 1
      /* SIP doesn't have axis mapping. */
d2641 1
a2641 1
      /* The Paper IV translation of DSS doesn't require an axis mapping. */
d2659 1
a2659 1
  /* Set MJDREF from JDREF. */
d2676 1
a2676 1
  /* Set the integer part of MJDREF from JDREFI. */
d2688 1
a2688 1
  /* Set the fractional part of MJDREF from JDREFF. */
d2704 1
a2704 1
  /* If EQUINOXa is currently undefined then set it from EPOCHa. */
d2722 1
a2722 1
  /* If ZSOURCEa is currently undefined then set it from VSOURCEa. */
d2724 1
a2724 1
    /* Convert relativistic Doppler velocity to redshift. */
d2766 1
a2766 1
    /* Interpret -TAB header keywords. */
d2773 2
a2774 2
      /* Prior and sequent distortions co-exist in this representation;
         ensure the latter gets DVERRa. */
d2779 1
a2779 1
  /* Translated distortion functions; apply only to the primary WCS. */
d2782 1
a2782 1
    /* SIP doesn't have alternates, nor axis mapping. */
d2790 2
a2791 2
    /* DSS doesn't have alternates, nor axis mapping.  This translation */
    /* follows Paper IV, Sect. 5.2 using the same variable names.       */
d2833 1
a2833 1
    /* Erase the approximate WCS provided in modern DSS headers. */
d2840 1
a2840 1
    /* TNX and ZPX don't have alternates, nor axis mapping. */
d2843 1
a2843 1
    /* Disassemble the core dump stored in the WATi_m strings. */
d2853 1
a2853 1
        /* Could contain "tan" or something else to be ignored. */
d2858 1
a2858 1
      /* The PROJPn parameters are duplicated on each ZPX axis. */
d2860 2
a2861 2
        /* Take those on the second (latitude) axis ignoring the other. */
        /* First we have to count them and allocate space in wcsprm.    */
d2868 1
a2868 1
        /* Allocate space. */
d2879 1
a2879 1
        /* Copy the values. */
d2895 1
a2895 1
      /* Read the control parameters. */
d2909 1
a2909 1
      /* How many coefficients are we expecting? */
d2913 1
a2913 1
        /* No cross terms. */
d2917 1
a2917 1
        /* Full cross terms. */
d2921 1
a2921 1
        /* Half cross terms. */
d2926 1
a2926 1
    /* Allocate memory for dpkeys. */
d2938 1
a2938 1
    /* Populate dpkeys. */
d2943 1
a2943 1
      /* Read the control parameters. */
d2957 1
a2957 1
      /* Polynomial type. */
d2960 1
a2960 1
        /* Chebyshev polynomial. */
d2963 1
a2963 1
        /* Legendre polynomial. */
d2966 1
a2966 1
        /* Polynomial is the sum of monomials. */
d2969 1
a2969 1
        /* Unknown code. */
d2973 1
a2973 1
      /* Read the scaling parameters. */
d2985 1
a2985 1
      /* Read the coefficients. */
@


7.3.1.1
log
@WCSLIB 7.3 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 7.3 2020/06/03 03:37:02 mcalabre Exp $
@


7.3.1.2
log
@Switched to C99 style commenting (i.e. using //) within the code.
@
text
@d2 1
d25 1
a25 1
  $Id: wcspih.l,v 7.3.1.1 2020/06/03 03:38:10 mcalabre Exp mcalabre $
d144 1
a144 1
//----------------------------------------------------------------------------
d169 1
a169 1
//----------------------------------------------------------------------------
d187 1
a187 1
// These global variables are required by YY_INPUT.
d191 1
a191 1
// Internal helper functions.
d208 1
a208 1
// Used in preempting the call to exit() by yy_fatal_error().
d215 1
a215 1
	// Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma.
d244 1
a244 1
	// Parameters used to implement YY_INPUT.
d248 1
a248 1
	// Our handle on the input stream.
d253 1
a253 1
	// For keeping tallies of keywords found.
d258 1
a258 1
	// If strict, then also reject.
d261 1
a261 1
	// Keyword parameters.
d266 1
a266 1
	// For decoding the keyvalue.
d271 1
a271 1
	// For keywords that require special handling.
d284 1
a284 1
	// The data structures produced.
d288 1
a288 1
	// Control variables.
d292 1
a292 1
	// Return here via longjmp() invoked by yy_fatal_error().
d630 1
a630 1
	    // Actually integer, but treated as float.
d686 1
a686 1
	    // Actually integer, but treated as float.
d1196 1
a1196 1
	  // SIP: axis 1 polynomial degree (not stored).
d1209 1
a1209 1
	  // SIP: axis 2 polynomial degree (not stored).
d1222 1
a1222 1
	  // SIP: axis 1 inverse polynomial degree (not stored).
d1235 1
a1235 1
	  // SIP: axis 2 inverse polynomial degree (not stored).
d1248 1
a1248 1
	  // SIP: axis 1 maximum distortion.
d1261 1
a1261 1
	  // SIP: axis 2 maximum distortion.
d1274 1
a1274 1
	  // SIP: axis 1 polynomial coefficient.
d1283 1
a1283 1
	  // SIP: axis 2 polynomial coefficient.
d1292 1
a1292 1
	  // SIP: axis 1 inverse polynomial coefficient.
d1301 1
a1301 1
	  // SIP: axis 2 inverse polynomial coefficient.
d1310 1
a1310 1
	  // DSS: LLH corner pixel coordinate 1.
d1322 1
a1322 1
	  // DSS: LLH corner pixel coordinate 2.
d1334 1
a1334 1
	  // DSS: plate centre x-coordinate in micron.
d1346 1
a1346 1
	  // DSS: plate centre y-coordinate in micron.
d1358 1
a1358 1
	  // DSS: pixel x-dimension in micron.
d1370 1
a1370 1
	  // DSS: pixel y-dimension in micron.
d1382 1
a1382 1
	  // DSS: plate centre, right ascension - hours.
d1394 1
a1394 1
	  // DSS: plate centre, right ascension - minutes.
d1406 1
a1406 1
	  // DSS: plate centre, right ascension - seconds.
d1418 1
a1418 1
	  // DSS: plate centre, declination - sign.
d1430 1
a1430 1
	  // DSS: plate centre, declination - degrees.
d1442 1
a1442 1
	  // DSS: plate centre, declination - arcmin.
d1454 1
a1454 1
	  // DSS: plate centre, declination - arcsec.
d1466 1
a1466 1
	  // DSS: plate identification (insufficient to trigger DSS).
d1478 1
a1478 1
	  // DSS: axis 1 polynomial coefficient.
d1487 1
a1487 1
	  // DSS: axis 2 polynomial coefficient.
d1496 1
a1496 1
	  // TNX or ZPX: string-encoded data array.
d1542 1
a1542 1
	    // Violates the basic FITS standard.
d1548 1
a1548 1
	    // Pretend we don't recognize it.
d1562 2
a1563 2
	  // Anything that has fallen through to this point must contain
	  // an invalid axis number.
d1569 1
a1569 1
	  // Let it go.
d1575 1
a1575 1
	    // Looks too much like a FITS WCS keyword not to flag it.
d1582 1
a1582 1
	    // Let it go.
d1628 1
a1628 1
	    // Pretend we don't recognize it.
d1643 2
a1644 2
	  // Anything that has fallen through to this point must contain
	  // an invalid axis number.
d1666 1
a1666 1
	  // This covers the defunct forms CD00i00j and PC00i00j.
d1681 1
a1681 1
	    // Pretend we don't recognize it.
d1704 1
a1704 1
	    // Looks too much like a FITS WCS keyword not to flag it.
d1711 1
a1711 1
	    // Pretend we don't recognize it.
d1756 1
a1756 1
	    // Pretend we don't recognize it.
d1771 2
a1772 2
	  // Anything that has fallen through to this point must contain
	  // an invalid axis number.
d1816 1
a1816 1
	    // Pretend we don't recognize it.
d1859 1
a1859 1
	  // SIP keywords.
d1879 1
a1879 1
	  // DSS keywords.
d1897 1
a1897 1
	  // Special handling for this iconic DSS keyword.
d1899 1
a1899 1
	    // Look for a minus sign.
d1912 1
a1912 1
	  // Do checks on i, j & m.
d1923 1
a1923 1
	      // Pretend we don't recognize it.
d1957 1
a1957 1
	    // Read the keyvalue.
d1974 1
a1974 1
	    // Read the keyvalue.
d1996 1
a1996 1
	    // Read the keyvalue as integer and fractional parts.
d2013 1
a2013 1
	    // Read the keyvalue.
d2016 1
a2016 1
	    // Squeeze out repeated quotes.
d2100 1
a2100 1
	    // Do first-pass bookkeeping.
d2105 1
a2105 1
	    // Store the value now that the keyrecord has been validated.
d2108 2
a2109 2
	      // The loop here is for keywords that apply
	      // to every alternate; these have a == 0.
d2118 1
a2118 1
	          // Translate a SIP keyword into DPja.
d2122 1
a2122 1
	          // SIP doesn't have alternates.
d2133 1
a2133 1
	          // All DSS keywords require special handling.
d2135 1
a2135 1
	            // Temporary parameter for DSS used by wcspih_final().
d2139 1
a2139 1
	            // Temporary parameter for DSS used by wcspih_final().
d2143 1
a2143 1
	            // Translate a DSS keyword into DQia.
d2148 1
a2148 1
	              // DSS doesn't have alternates.
d2153 1
a2153 1
	              // Also required by wcspih_final().
d2161 1
a2161 1
	          // String array for TNX and ZPX used by wcspih_final().
d2165 1
a2165 1
	          // An "ordinary" keyword.
d2168 1
a2168 1
	            // Additional auxiliary parameter.
d2174 1
a2174 1
	            // Distortion parameter of some kind.
d2176 1
a2176 1
	              // Prior distortion.
d2179 1
a2179 1
	              // Sequent distortion.
d2186 1
a2186 1
	            // A parameter that lives directly in wcsprm.
d2195 1
a2195 1
	            // Apply keyword parameterization.
d2216 1
a2216 1
	            // Flag presence of PCi_ja, or CDi_ja and/or CROTAia.
d2223 1
a2223 1
	            // Split MJDREF and JDREF into integer and fraction.
d2232 1
a2232 1
	            // Apply keyword parameterization.
d2315 1
a2315 1
	      // Preserve discards.
d2332 1
a2332 1
	      // Preserve rejects.
d2354 1
a2354 1
	  // Throw away the rest of the line and reset for the next one.
d2379 1
a2379 1
	  // End-of-input.
d2470 2
a2471 2
  // On the first pass alts[] is used to determine the number of axes
  // for each of the 27 possible alternate coordinate descriptions.
d2489 1
a2489 1
  // i or j can be greater than naxis.
d2498 1
a2498 1
  // Type of distortions present.
d2501 1
a2501 1
  // Count PVi_ma, PSi_ma, DPja, or DQia keywords.
d2531 1
a2531 1
  // Find the number of coordinate descriptions.
d2538 2
a2539 2
    // NAXIS is non-zero but there were no WCS keywords with an alternate
    // version code; create a default WCS with blank alternate version.
d2545 1
a2545 1
    // Allocate memory for the required number of wcsprm structs.
d2552 2
a2553 2
      // DPja.NAXES and DPja.OFFSET.j to be added for SIP (see below and
      // wcspih_final()).
d2557 1
a2557 1
      // DPja.NAXES to be added for DSS (see below and wcspih_final()).
d2561 1
a2561 1
    // Initialize each wcsprm struct.
d2574 1
a2574 1
        // Record the alternate version code.
d2579 1
a2579 1
        // Record in wcsname whether this is a default description.
d2584 1
a2584 1
        // Any additional auxiliary keywords present?
d2591 1
a2591 1
        // Any distortions present?
d2597 1
a2597 1
          // Attach it to linprm.  Also inits it.
d2609 1
a2609 1
          // Attach it to linprm.  Also inits it.
d2616 1
a2616 1
        // On the second pass alts[] indexes the array of wcsprm structs.
d2622 1
a2622 1
        // Signal that there is no wcsprm for this alt.
d2628 3
a2630 3
    // Translated distortion?  Neither SIP nor DSS have alternates, so the
    // presence of keywords for either (not both together), as flagged by
    // distran, necessarily refers to the primary representation.
d2635 1
a2635 1
      // SIP doesn't have axis mapping.
d2644 1
a2644 1
      // The Paper IV translation of DSS doesn't require an axis mapping.
d2662 1
a2662 1
  // Set MJDREF from JDREF.
d2679 1
a2679 1
  // Set the integer part of MJDREF from JDREFI.
d2691 1
a2691 1
  // Set the fractional part of MJDREF from JDREFF.
d2707 1
a2707 1
  // If EQUINOXa is currently undefined then set it from EPOCHa.
d2725 1
a2725 1
  // If ZSOURCEa is currently undefined then set it from VSOURCEa.
d2727 1
a2727 1
    // Convert relativistic Doppler velocity to redshift.
d2769 1
a2769 1
    // Interpret -TAB header keywords.
d2776 2
a2777 2
      // Prior and sequent distortions co-exist in this representation;
      // ensure the latter gets DVERRa.
d2782 1
a2782 1
  // Translated distortion functions; apply only to the primary WCS.
d2785 1
a2785 1
    // SIP doesn't have alternates, nor axis mapping.
d2793 2
a2794 2
    // DSS doesn't have alternates, nor axis mapping.  This translation
    // follows Paper IV, Sect. 5.2 using the same variable names.
d2836 1
a2836 1
    // Erase the approximate WCS provided in modern DSS headers.
d2843 1
a2843 1
    // TNX and ZPX don't have alternates, nor axis mapping.
d2846 1
a2846 1
    // Disassemble the core dump stored in the WATi_m strings.
d2856 1
a2856 1
        // Could contain "tan" or something else to be ignored.
d2861 1
a2861 1
      // The PROJPn parameters are duplicated on each ZPX axis.
d2863 2
a2864 2
        // Take those on the second (latitude) axis ignoring the other.
        // First we have to count them and allocate space in wcsprm.
d2871 1
a2871 1
        // Allocate space.
d2882 1
a2882 1
        // Copy the values.
d2898 1
a2898 1
      // Read the control parameters.
d2912 1
a2912 1
      // How many coefficients are we expecting?
d2916 1
a2916 1
        // No cross terms.
d2920 1
a2920 1
        // Full cross terms.
d2924 1
a2924 1
        // Half cross terms.
d2929 1
a2929 1
    // Allocate memory for dpkeys.
d2941 1
a2941 1
    // Populate dpkeys.
d2946 1
a2946 1
      // Read the control parameters.
d2960 1
a2960 1
      // Polynomial type.
d2963 1
a2963 1
        // Chebyshev polynomial.
d2966 1
a2966 1
        // Legendre polynomial.
d2969 1
a2969 1
        // Polynomial is the sum of monomials.
d2972 1
a2972 1
        // Unknown code.
d2976 1
a2976 1
      // Read the scaling parameters.
d2988 1
a2988 1
      // Read the coefficients.
@


7.3.1.3
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2021, Mark Calabretta
d24 1
a24 1
  $Id: wcspih.l,v 7.3.1.2 2020/08/17 11:19:09 mcalabre Exp mcalabre $
@


7.3.1.4
log
@Removed my email address from the copyright notice.
@
text
@d20 2
d24 1
a24 1
  $Id: wcspih.l,v 7.3.1.3 2021/01/19 14:09:10 mcalabre Exp mcalabre $
@


7.2
log
@WCSLIB 7.2
@
text
@d3 1
a3 1
  WCSLIB 7.2 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 7.1.1.1 2019/12/31 13:28:19 mcalabre Exp mcalabre $
d485 1
a485 1
	  } else if (a == ' ' || relax & WCSHDR_VELREFa) {
d591 12
a602 3
^DATEREF" " {
	  valtype = STRING;
	  vptr    = wcstem.dateref;
d604 3
a606 2
	  keyname = "DATEREF";
	  BEGIN(CCCCCCCC);
d609 12
a620 3
^MJDREF"  " {
	  valtype = FLOAT2;
	  vptr    = wcstem.mjdref;
d622 3
a624 2
	  keyname = "MJDREF";
	  BEGIN(CCCCCCCC);
d627 13
a639 4
^MJDREFI" " {
	  /* Actually integer, but treated as float. */
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
d641 3
a643 2
	  keyname = "MJDREFI";
	  BEGIN(CCCCCCCC);
d646 12
a657 3
^MJDREFF" " {
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref + 1;
d659 3
a661 2
	  keyname = "MJDREFF";
	  BEGIN(CCCCCCCC);
d664 13
a676 4
^JDREF"   " {
	  valtype = FLOAT2;
	  vptr    = wcstem.mjdref;
	  special = wcspih_jdref;
d678 3
a680 2
	  keyname = "JDREF";
	  BEGIN(CCCCCCCC);
d683 14
a696 5
^JDREFI"  " {
	  /* Actually integer, but treated as float. */
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
	  special = wcspih_jdrefi;
d698 3
a700 2
	  keyname = "JDREFI";
	  BEGIN(CCCCCCCC);
d703 13
a715 4
^JDREFF"  " {
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
	  special = wcspih_jdreff;
d717 3
a719 2
	  keyname = "JDREFF";
	  BEGIN(CCCCCCCC);
d1807 1
a1807 1
	  } else if (a == ' ' || relax & WCSHDR_CROTAia) {
@


7.2.1.1
log
@WCSLIB 7.2 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 7.2 2020/03/09 07:31:23 mcalabre Exp $
@


7.2.1.2
log
@Under control of WCSHDR_DATEREF, optionally accept DATE-REF, MJD-REF,
MJD-REFI, MJD-REFF, JDREF, JD-REFI, and JD-REFF as synonyms for the
standard keywords, DATEREF, MJDREF, MJDREFI, MJDREFF, JDREF, JDREFI, and
JDREFF.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 7.2.1.1 2020/03/09 07:34:50 mcalabre Exp mcalabre $
d485 1
a485 1
	  } else if ((a == ' ') || (relax & WCSHDR_VELREFa)) {
d591 3
a593 5
^DATEREF" " |
^DATE-REF {
	  if ((yytext[4] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = STRING;
	    vptr    = wcstem.dateref;
d595 2
a596 10
	    keyname = "DATEREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the DATE-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d599 3
a601 5
^MJDREF"  " |
^MJD-REF" " {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT2;
	    vptr    = wcstem.mjdref;
d603 2
a604 10
	    keyname = "MJDREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d607 4
a610 6
^MJDREFI" " |
^MJD-REFI {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    /* Actually integer, but treated as float. */
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
d612 2
a613 10
	    keyname = "MJDREFI";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REFI keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d616 3
a618 5
^MJDREFF" " |
^MJD-REFF {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref + 1;
d620 2
a621 10
	    keyname = "MJDREFF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REFF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d624 4
a627 6
^JDREF"   " |
^JD-REF"  " {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT2;
	    vptr    = wcstem.mjdref;
	    special = wcspih_jdref;
d629 2
a630 10
	    keyname = "JDREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d633 5
a637 7
^JDREFI"  " |
^JD-REFI {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    /* Actually integer, but treated as float. */
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
	    special = wcspih_jdrefi;
d639 2
a640 10
	    keyname = "JDREFI";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REFI keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d643 4
a646 6
^JDREFF"  " |
^JD-REFF {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
	    special = wcspih_jdreff;
d648 2
a649 10
	    keyname = "JDREFF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REFF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d1737 1
a1737 1
	  } else if ((a == ' ') || (relax & WCSHDR_CROTAia)) {
@


7.1
log
@WCSLIB 7.1
@
text
@d3 1
a3 1
  WCSLIB 7.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 6.4.1.4 2019/12/31 03:28:03 mcalabre Exp mcalabre $
@


7.1.1.1
log
@WCSLIB 7.1 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 7.1 2019/12/31 13:25:19 mcalabre Exp $
@


6.4
log
@WCSLIB 6.4
@
text
@d3 2
a4 2
  WCSLIB 6.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2019, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 6.3.1.1 2019/07/12 07:34:37 mcalabre Exp mcalabre $
d114 1
d194 4
a197 4
static int wcspih_inits(int naxis, int alts[], int dpq[], int npv[],
             int nps[], int ndp[], int ndq[], int distran, int *nwcs,
	     struct wcsprm **wcs);
static void wcspih_naxes(int naxis, int i, int j, char a, int distype,
d221 5
a225 4
	int  altlin, alts[27], distran, distype, dpq[27], dssflag, gotone,
	     ialt, inttmp, ipass, ipx, ix, jx, naxis, ndp[27], ndq[27],
	     nother, *npptr, nps[27], npass, npv[27], nvalid, rectype,
	     sipflag, status, valtype, voff, watflag, watn;
d228 1
d276 2
d1014 46
d2031 1
a2031 1
	    wcspih_naxes(naxis, i, j, a, distype, alts, dpq, npptr);
d2095 1
a2095 1
	          /* An ordinary keyword. */
d2097 5
a2101 3
	          if (distype == 0) {
	            voff = (char *)vptr - (char *)(&wcstem);
	            wptr = (void *)((char *)wcsp + voff);
d2103 2
a2104 2
	          } else {
	            voff = (char *)vptr - (char *)(&distem);
d2112 1
d2114 5
d2282 2
d2300 1
d2311 2
a2312 2
	    if ((status = wcspih_inits(naxis, alts, dpq, npv, nps, ndp, ndq,
	                               distran, nwcs, wcs)) ||
d2351 1
d2389 1
a2389 1
void wcspih_naxes(
d2443 1
a2443 1
int wcspih_inits(
d2451 1
d2470 1
a2470 1
    wcspih_naxes(naxis, 0, 0, ' ', 0, alts, dpq, 0x0);
d2512 7
@


6.4.1.1
log
@WCSLIB 6.4 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 6.4 2019/08/15 09:30:18 mcalabre Exp $
@


6.4.1.2
log
@Use the ptrdiff_t data type correctly to quell warnings from Microsoft
Visual C++ (MSVC).
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 6.4.1.1 2019/08/15 09:31:29 mcalabre Exp mcalabre $
a113 1
#include <stddef.h>
d223 1
a223 2
	     sipflag, status, valtype, watflag, watn;
	ptrdiff_t voff;
@


6.4.1.3
log
@Parse the Solar-related keyrecords RSUN_REF, DSUN_OBS, CRLN_OBS, CRLT_OBS,
HGLN_OBS, and HGLT_OBS and record their keyvalues in an auxprm struct.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 6.4.1.2 2019/12/16 03:22:01 mcalabre Exp mcalabre $
d194 4
a197 4
static int wcspih_init1(int naxis, int alts[], int dpq[], int npv[],
             int nps[], int ndp[], int ndq[], int auxprm, int distran,
             int *nwcs, struct wcsprm **wcs);
static void wcspih_pass1(int naxis, int i, int j, char a, int distype,
d221 4
a224 4
	int  altlin, alts[27], auxprm, distran, distype, dpq[27], dssflag,
	     gotone, ialt, inttmp, ipass, ipx, ix, jx, naux, naxis,
	     ndp[27], ndq[27], nother, *npptr, nps[27], npass, npv[27],
	     nvalid, rectype, sipflag, status, valtype, watflag, watn;
a227 1
	struct auxprm *auxp, auxtem;
a274 2
	auxprm  = 0;
	naux    = 0;
a1010 46
^RSUN_REF {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.rsun_ref);
	
	  keyname = "RSUN_REF";
	  BEGIN(CCCCCCCC);
	}

^DSUN_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.dsun_obs);
	
	  keyname = "DSUN_OBS";
	  BEGIN(CCCCCCCC);
	}

^CRLN_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.crln_obs);
	
	  keyname = "CRLN_OBS";
	  BEGIN(CCCCCCCC);
	}

^HGLN_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.hgln_obs);
	
	  keyname = "HGLN_OBS";
	  BEGIN(CCCCCCCC);
	}

^CRLT_OBS |
^HGLT_OBS {
	  valtype = FLOAT;
	  auxprm  = 1;
	  vptr    = &(auxtem.hglt_obs);
	
	  keyname = "HGLT_OBS";
	  BEGIN(CCCCCCCC);
	}

d1982 1
a1982 1
	    wcspih_pass1(naxis, i, j, a, distype, alts, dpq, npptr);
d2046 1
a2046 1
	          /* An "ordinary" keyword. */
d2048 3
a2050 5
	          if (auxprm) {
	            /* Additional auxiliary parameter. */
	            auxp = wcsp->aux;
	            voff = (char *)vptr - (char *)(&auxtem);
	            wptr = (void *)((char *)auxp + voff);
d2052 2
a2053 2
	          } else if (distype) {
	            /* Distortion parameter of some kind. */
a2060 1
	            voff = (char *)vptr - (char *)(&distem);
a2061 5
	
	          } else {
	            /* A parameter that lives directly in wcsprm. */
	            voff = (char *)vptr - (char *)(&wcstem);
	            wptr = (void *)((char *)wcsp + voff);
a2224 2
	  naux += auxprm;
	
a2240 1
	  auxprm  = 0;
d2251 2
a2252 2
	    if ((status = wcspih_init1(naxis, alts, dpq, npv, nps, ndp, ndq,
	                               naux, distran, nwcs, wcs)) ||
a2290 1
	    auxprm  = 0;
d2328 1
a2328 1
void wcspih_pass1(
d2382 1
a2382 1
int wcspih_init1(
a2389 1
  int naux,
d2408 1
a2408 1
    wcspih_pass1(naxis, 0, 0, ' ', 0, alts, dpq, 0x0);
a2449 7
        }

        /* Any additional auxiliary keywords present? */
        if (naux) {
          if (wcsauxi(1, wcsp)) {
            return WCSHDRERR_MEMORY;
          }
@


6.4.1.4
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2020, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 6.4.1.3 2019/12/31 02:30:08 mcalabre Exp mcalabre $
@


6.3
log
@WCSLIB 6.3
@
text
@d3 1
a3 1
  WCSLIB 6.3 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 6.2.1.3 2019/07/08 08:02:29 mcalabre Exp mcalabre $
@


6.3.1.1
log
@WCSLIB 6.3 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 6.3 2019/07/12 07:33:39 mcalabre Exp $
@


6.2
log
@WCSLIB 6.2
@
text
@d3 2
a4 2
  WCSLIB 6.2 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2018, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 6.1.1.1 2018/10/19 08:36:15 mcalabre Exp mcalabre $
d71 1
@


6.2.1.1
log
@WCSLIB 6.2 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 6.2 2018/10/20 10:03:13 mcalabre Exp $
@


6.2.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2019, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 6.2.1.1 2018/10/20 10:04:15 mcalabre Exp mcalabre $
@


6.2.1.3
log
@Set '%option noinput' to quench -Wunused-function compiler warnings that
arise from not using flex's input() function.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 6.2.1.3 2019/07/08 06:55:39 mcalabre Exp mcalabre $
a70 1
%option noinput
@


6.1
log
@WCSLIB 6.1
@
text
@d3 1
a3 1
  WCSLIB 6.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.20.1.2 2018/10/19 06:38:35 mcalabre Exp mcalabre $
@


6.1.1.1
log
@WCSLIB 6.1 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 6.1 2018/10/19 08:35:17 mcalabre Exp $
@


5.20
log
@WCSLIB 5.20
@
text
@d3 1
a3 1
  WCSLIB 5.20 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.19.1.1 2018/07/26 15:41:40 mcalabre Exp mcalabre $
d105 1
a105 1
%x VALUE INTEGER_VAL FLOAT_VAL STRING_VAL
d127 3
a129 2
#define STRING  2
#define RECORD  3
d186 2
a187 2
char *wcspih_hdr;
int  wcspih_nkeyrec;
d189 14
a202 6
int wcspih_final(int ndp[], int ndq[], int distran, double dsstmp[],
        char *wat[], int *nwcs, struct wcsprm **wcs);
int wcspih_inits(int naxis, int alts[], int dpq[], int npv[], int nps[],
        int ndp[], int ndq[], int distran, int *nwcs, struct wcsprm **wcs);
void wcspih_naxes(int naxis, int i, int j, char a, int distype, int alts[],
        int dpq[], int *npptr);
d204 1
a204 2
int wcspih_epoch(double *wptr, double epoch);
int wcspih_vsource(double *wptr, double vsource);
d223 1
a223 1
	double dbltmp, dsstmp[20];
d227 2
a228 1
	int (*special)(double *, double);
d270 1
d472 25
d521 151
d681 1
a681 1
^DATE-OBS {
d683 28
a710 1
	  vptr    = wcstem.dateobs;
d713 1
a713 1
	  keyname = "DATE-OBS";
d717 4
a720 2
^EPOCH{ALT}"  " {
	  sscanf(yytext, "EPOCH%c", &a);
d722 8
a729 3
	  if (relax & WCSHDR_strict) {
	    errmsg = "the EPOCH keyword is deprecated, use EQUINOXa";
	    BEGIN(ERROR);
d731 8
a738 4
	  } else if (a == ' ' || relax & WCSHDR_EPOCHa) {
	    valtype = FLOAT;
	    vptr    = &(wcstem.equinox);
	    special = wcspih_epoch;
d740 8
a747 1
	    unput(a);
d749 8
a756 2
	    keyname = "EPOCH";
	    BEGIN(CCCCCCCa);
d758 8
a765 3
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "EPOCH keyword may not have an alternate version code";
	    BEGIN(ERROR);
d767 2
a768 3
	  } else {
	    BEGIN(DISCARD);
	  }
d771 1
a771 1
^EQUINOX {
d773 2
a774 1
	  vptr    = &(wcstem.equinox);
d776 2
a777 2
	  keyname = "EQUINOXa";
	  BEGIN(CCCCCCCa);
d780 1
a780 1
^MJD-AVG" " {
d782 2
a783 1
	  vptr    = &(wcstem.mjdavg);
d785 7
d794 1
a794 1
	  keyname = "MJD-AVG";
d798 1
a798 1
^MJD-OBS" " {
d800 2
a801 1
	  vptr    = &(wcstem.mjdobs);
d803 8
d813 1
a813 1
	  keyname = "MJD-OBS";
a819 1
	
a828 1
	
d838 1
d840 25
d867 9
a875 1
	  keyname = "OBSGEO-Z";
d906 34
a955 16
^SSYSSRC {
	  valtype = STRING;
	  vptr    = wcstem.ssyssrc;
	
	  keyname = "SSYSSRCa";
	  BEGIN(CCCCCCCa);
	}

^VELANGL {
	  valtype = FLOAT;
	  vptr    = &(wcstem.velangl);
	
	  keyname = "VELANGLa";
	  BEGIN(CCCCCCCa);
	}

a963 25
^VELREF{ALT}" " {
	  sscanf(yytext, "VELREF%c", &a);
	
	  if (relax & WCSHDR_strict) {
	    errmsg = "the VELREF keyword is deprecated, use SPECSYSa";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_VELREFa) {
	    valtype = INTEGER;
	    vptr    = &(wcstem.velref);
	
	    unput(a);
	
	    keyname = "VELREF";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VELREF keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

d984 9
a992 1
^WCSNAME {
d994 1
a994 1
	  vptr    = wcstem.wcsname;
d996 1
a996 1
	  keyname = "WCSNAMEa";
d1000 1
a1000 1
^ZSOURCE {
d1002 1
a1002 1
	  vptr    = &(wcstem.zsource);
d1004 1
a1004 1
	  keyname = "ZSOURCEa";
d1810 2
d1854 22
d1881 1
a1881 1
<FLOAT_VAL>. {
d2081 1
a2081 1
	              special(wptr, dbltmp);
d2092 9
d2236 1
d2286 1
d2514 45
d2562 1
a2562 1
int wcspih_epoch(double *equinox, double epoch)
d2567 1
a2567 1
    *equinox = epoch;
d2578 1
a2578 1
int wcspih_vsource(double *zsource, double vsource)
d2586 1
a2586 1
    beta = vsource/c;
d2591 11
@


5.20.1.1
log
@WCSLIB 5.20 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.20 2018/10/05 05:32:41 mcalabre Exp $
@


5.20.1.2
log
@Added support for time-related WCS keywords (Paper VII).  Added a new class
of helper functions, chekval, to do basic validity checking on keyvalues.
Declared all helper functions static.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.20.1.1 2018/10/05 05:33:33 mcalabre Exp mcalabre $
d105 1
a105 1
%x VALUE INTEGER_VAL FLOAT_VAL FLOAT2_VAL STRING_VAL
d127 2
a128 3
#define FLOAT2  2
#define STRING  3
#define RECORD  4
d185 2
a186 2
static char *wcspih_hdr;
static int  wcspih_nkeyrec;
d188 6
a193 14
/* Internal helper functions. */
static int wcspih_final(int ndp[], int ndq[], int distran, double dsstmp[],
             char *wat[], int *nwcs, struct wcsprm **wcs);
static int wcspih_inits(int naxis, int alts[], int dpq[], int npv[],
             int nps[], int ndp[], int ndq[], int distran, int *nwcs,
	     struct wcsprm **wcs);
static void wcspih_naxes(int naxis, int i, int j, char a, int distype,
             int alts[], int dpq[], int *npptr);

static int wcspih_jdref(double *wptr,   const double *jdref);
static int wcspih_jdrefi(double *wptr,  const double *jdrefi);
static int wcspih_jdreff(double *wptr,  const double *jdreff);
static int wcspih_epoch(double *wptr,   const double *epoch);
static int wcspih_vsource(double *wptr, const double *vsource);
d195 2
a196 1
static int wcspih_timepixr(double timepixr);
d215 1
a215 1
	double dbltmp, dbl2tmp[2], dsstmp[20];
d219 1
a219 2
	int (*chekval)(double);
	int (*special)(double *, const double *);
a260 1
	chekval = 0x0;
a461 25
^VELREF{ALT}" " {
	  sscanf(yytext, "VELREF%c", &a);
	
	  if (relax & WCSHDR_strict) {
	    errmsg = "the VELREF keyword is deprecated, use SPECSYSa";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_VELREFa) {
	    valtype = INTEGER;
	    vptr    = &(wcstem.velref);
	
	    unput(a);
	
	    keyname = "VELREF";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VELREF keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

a485 151
^CZPHS	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.czphs);
	
	  keyname = "CZPHSia";
	  BEGIN(CCCCCia);
	}

^CPERI	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cperi);
	
	  keyname = "CPERIia";
	  BEGIN(CCCCCia);
	}

^WCSNAME {
	  valtype = STRING;
	  vptr    = wcstem.wcsname;
	
	  keyname = "WCSNAMEa";
	  BEGIN(CCCCCCCa);
	}

^TIMESYS" " {
	  valtype = STRING;
	  vptr    = wcstem.timesys;
	
	  keyname = "TIMESYS";
	  BEGIN(CCCCCCCC);
	}

^TREFPOS" " {
	  valtype = STRING;
	  vptr    = wcstem.trefpos;
	
	  keyname = "TREFPOS";
	  BEGIN(CCCCCCCC);
	}

^TREFDIR" " {
	  valtype = STRING;
	  vptr    = wcstem.trefdir;
	
	  keyname = "TREFDIR";
	  BEGIN(CCCCCCCC);
	}

^PLEPHEM" " {
	  valtype = STRING;
	  vptr    = wcstem.plephem;
	
	  keyname = "PLEPHEM";
	  BEGIN(CCCCCCCC);
	}

^TIMEUNIT {
	  valtype = STRING;
	  vptr    = wcstem.timeunit;
	
	  keyname = "TIMEUNIT";
	  BEGIN(CCCCCCCC);
	}

^DATEREF" " {
	  valtype = STRING;
	  vptr    = wcstem.dateref;
	
	  keyname = "DATEREF";
	  BEGIN(CCCCCCCC);
	}

^MJDREF"  " {
	  valtype = FLOAT2;
	  vptr    = wcstem.mjdref;
	
	  keyname = "MJDREF";
	  BEGIN(CCCCCCCC);
	}

^MJDREFI" " {
	  /* Actually integer, but treated as float. */
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
	
	  keyname = "MJDREFI";
	  BEGIN(CCCCCCCC);
	}

^MJDREFF" " {
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref + 1;
	
	  keyname = "MJDREFF";
	  BEGIN(CCCCCCCC);
	}

^JDREF"   " {
	  valtype = FLOAT2;
	  vptr    = wcstem.mjdref;
	  special = wcspih_jdref;
	
	  keyname = "JDREF";
	  BEGIN(CCCCCCCC);
	}

^JDREFI"  " {
	  /* Actually integer, but treated as float. */
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
	  special = wcspih_jdrefi;
	
	  keyname = "JDREFI";
	  BEGIN(CCCCCCCC);
	}

^JDREFF"  " {
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
	  special = wcspih_jdreff;
	
	  keyname = "JDREFF";
	  BEGIN(CCCCCCCC);
	}

^TIMEOFFS {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timeoffs);
	
	  keyname = "TIMEOFFS";
	  BEGIN(CCCCCCCC);
	}

^DATE-OBS {
	  valtype = STRING;
	  vptr    = wcstem.dateobs;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-OBS";
	  BEGIN(CCCCCCCC);
	}

^DATE-BEG {
	  valtype = STRING;
	  vptr    = wcstem.datebeg;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-BEG";
	  BEGIN(CCCCCCCC);
	}

d495 1
a495 1
^DATE-END {
d497 1
a497 1
	  vptr    = wcstem.dateend;
d500 1
a500 1
	  keyname = "DATE-END";
d504 2
a505 4
^MJD-OBS" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdobs);
	  if (ctrl < -10) keep = keyrec;
d507 3
a509 8
	  keyname = "MJD-OBS";
	  BEGIN(CCCCCCCC);
	}

^MJD-BEG" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdbeg);
	  if (ctrl < -10) keep = keyrec;
d511 4
a514 8
	  keyname = "MJD-BEG";
	  BEGIN(CCCCCCCC);
	}

^MJD-AVG" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdavg);
	  if (ctrl < -10) keep = keyrec;
d516 1
a516 8
	  keyname = "MJD-AVG";
	  BEGIN(CCCCCCCC);
	}

^MJD-END" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdend);
	  if (ctrl < -10) keep = keyrec;
d518 2
a519 8
	  keyname = "MJD-END";
	  BEGIN(CCCCCCCC);
	}

^JEPOCH"  " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.jepoch);
	  if (ctrl < -10) keep = keyrec;
d521 3
a523 8
	  keyname = "JEPOCH";
	  BEGIN(CCCCCCCC);
	}

^BEPOCH"  " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.bepoch);
	  if (ctrl < -10) keep = keyrec;
d525 3
a527 2
	  keyname = "BEPOCH";
	  BEGIN(CCCCCCCC);
d530 1
a530 1
^TSTART"  " {
d532 1
a532 2
	  vptr    = &(wcstem.tstart);
	  if (ctrl < -10) keep = keyrec;
d534 2
a535 2
	  keyname = "TSTART";
	  BEGIN(CCCCCCCC);
d538 1
a538 1
^TSTOP"   " {
d540 1
a540 2
	  vptr    = &(wcstem.tstop);
	  if (ctrl < -10) keep = keyrec;
a541 7
	  keyname = "TSTOP";
	  BEGIN(CCCCCCCC);
	}

^XPOSURE" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.xposure);
d544 1
a544 1
	  keyname = "XPOSURE";
d548 1
a548 1
^TELAPSE" " {
d550 1
a550 2
	  vptr    = &(wcstem.telapse);
	  if (ctrl < -10) keep = keyrec;
a551 7
	  keyname = "TELAPSE";
	  BEGIN(CCCCCCCC);
	}

^TIMSYER" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timsyer);
d554 1
a554 29
	  keyname = "TIMSYER";
	  BEGIN(CCCCCCCC);
	}

^TIMRDER" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timrder);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMRDER";
	  BEGIN(CCCCCCCC);
	}

^TIMEDEL" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timedel);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMEDEL";
	  BEGIN(CCCCCCCC);
	}

^TIMEPIXR {
	  valtype = FLOAT;
	  vptr    = &(wcstem.timepixr);
	  chekval = wcspih_timepixr;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMEPIXR";
d561 1
d571 1
d581 1
a587 35
^OBSGEO-L {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 3;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-L";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-B {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 4;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-B";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-H {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 5;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-H";
	  BEGIN(CCCCCCCC);
	}

^OBSORBIT {
	  valtype = STRING;
	  vptr    = wcstem.obsorbit;
	
	  keyname = "OBSORBIT";
	  BEGIN(CCCCCCCC);
	}

d615 3
a617 2
^EPOCH{ALT}"  " {
	  sscanf(yytext, "EPOCH%c", &a);
d619 2
a620 21
	  if (relax & WCSHDR_strict) {
	    errmsg = "the EPOCH keyword is deprecated, use EQUINOXa";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_EPOCHa) {
	    valtype = FLOAT;
	    vptr    = &(wcstem.equinox);
	    special = wcspih_epoch;
	
	    unput(a);
	
	    keyname = "EPOCH";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "EPOCH keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d623 3
a625 3
^EQUINOX {
	  valtype = FLOAT;
	  vptr    = &(wcstem.equinox);
d627 1
a627 1
	  keyname = "EQUINOXa";
d631 1
a631 1
^SPECSYS {
d633 1
a633 1
	  vptr    = wcstem.specsys;
d635 1
a635 1
	  keyname = "SPECSYSa";
d639 3
a641 3
^SSYSOBS {
	  valtype = STRING;
	  vptr    = wcstem.ssysobs;
d643 1
a643 1
	  keyname = "SSYSOBSa";
d655 25
d700 1
a700 9
^ZSOURCE {
	  valtype = FLOAT;
	  vptr    = &(wcstem.zsource);
	
	  keyname = "ZSOURCEa";
	  BEGIN(CCCCCCCa);
	}

^SSYSSRC {
d702 1
a702 1
	  vptr    = wcstem.ssyssrc;
d704 1
a704 1
	  keyname = "SSYSSRCa";
d708 1
a708 1
^VELANGL {
d710 1
a710 1
	  vptr    = &(wcstem.velangl);
d712 1
a712 1
	  keyname = "VELANGLa";
a1517 2
	    } else if (valtype == FLOAT2) {
	      BEGIN(FLOAT2_VAL);
a1559 22

	    if (chekval && chekval(dbltmp)) {
	      errmsg = "invalid keyvalue";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(COMMENT);
	    }
	  }
	}

<FLOAT_VAL>. {
	  errmsg = "a floating-point value was expected";
	  BEGIN(ERROR);
	}

<FLOAT2_VAL>{FLOAT} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
	
	  } else {
	    /* Read the keyvalue as integer and fractional parts. */
	    wcsutil_str2double2(yytext, dbl2tmp);
d1565 1
a1565 1
<FLOAT2_VAL>. {
d1765 1
a1765 1
	              special(wptr, &dbltmp);
a1775 9
	          } else if (valtype == FLOAT2) {
	            /* Split MJDREF and JDREF into integer and fraction.*/
	            if (special) {
	              special(wptr, dbl2tmp);
	            } else {
	              *((double *)wptr) = dbl2tmp[0];
	              *((double *)wptr + 1) = dbl2tmp[1];
	            }
	
a1910 1
	  chekval = 0x0;
a1959 1
	    chekval = 0x0;
a2186 45
* Interpret the JDREF, JDREFI, and JDREFF keywords.
*---------------------------------------------------------------------------*/

int wcspih_jdref(double *mjdref, const double *jdref)

{
  /* Set MJDREF from JDREF. */
  if (undefined(mjdref[0] && undefined(mjdref[1]))) {
    mjdref[0] = jdref[0] - 2400000.0;
    mjdref[1] = jdref[1] - 0.5;

    if (mjdref[1] < 0.0) {
      mjdref[0] -= 1.0;
      mjdref[1] += 1.0;
    }
  }

  return 0;
}

int wcspih_jdrefi(double *mjdref, const double *jdrefi)

{
  /* Set the integer part of MJDREF from JDREFI. */
  if (undefined(mjdref[0])) {
    mjdref[0] = *jdrefi - 2400000.5;
  }

  return 0;
}


int wcspih_jdreff(double *mjdref, const double *jdreff)

{
  /* Set the fractional part of MJDREF from JDREFF. */
  if (undefined(mjdref[1])) {
    mjdref[1] = *jdreff;
  }

  return 0;
}


/*----------------------------------------------------------------------------
d2190 1
a2190 1
int wcspih_epoch(double *equinox, const double *epoch)
d2195 1
a2195 1
    *equinox = *epoch;
d2206 1
a2206 1
int wcspih_vsource(double *zsource, const double *vsource)
d2214 1
a2214 1
    beta = *vsource/c;
a2218 11
}


/*----------------------------------------------------------------------------
* Check validity of a TIMEPIXR keyvalue.
*---------------------------------------------------------------------------*/

int wcspih_timepixr(double timepixr)

{
  return (timepixr < 0.0 || 1.0 < timepixr);
@


5.19
log
@WCSLIB 5.19
@
text
@d3 1
a3 1
  WCSLIB 5.19 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.18.1.2 2018/07/24 14:03:44 mcalabre Exp mcalabre $
@


5.19.1.1
log
@WCSLIB 5.19 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.19 2018/07/26 15:37:04 mcalabre Exp $
@


5.18
log
@WCSLIB 5.18
@
text
@d3 1
a3 1
  WCSLIB 5.18 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.17.1.5 2018/01/10 08:25:34 mcalabre Exp mcalabre $
d2236 1
a2236 1
  char   field[16], *wp, wpoly[12], wtype[8];
@


5.18.1.1
log
@WCSLIB 5.18 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.18 2018/01/10 08:32:14 mcalabre Exp $
@


5.18.1.2
log
@In wcspih_final(), increased the size of the sprintf() output buffer,
field[], to avert -Wformat-overflow warnings from gcc 8.1.0 (with
-DFORTIFY_SOURCE=2).
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.18.1.1 2018/01/10 08:33:04 mcalabre Exp mcalabre $
d2236 1
a2236 1
  char   field[32], *wp, wpoly[12], wtype[8];
@


5.17
log
@WCSLIB 5.17
@
text
@d3 2
a4 2
  WCSLIB 5.17 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2017, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 5.16.1.4 2017/09/12 14:20:36 mcalabre Exp mcalabre $
d74 1
d137 33
a169 2
#define YY_DECL int wcspih(char *header, int nkeyrec, int relax, int ctrl, \
                           int *nreject, int *nwcs, struct wcsprm **wcs)
a219 1
	int yylex_destroy(void);
a1924 1
	      yylex_destroy();
d1965 1
a1965 1
	    yyrestart(yyin);
a1967 1
	    yylex_destroy();
a2087 5
    /* Record the current values of NPVMAX, NPSMAX, and NDPMAX. */
    npvmax = wcsnpv(-1);
    npsmax = wcsnps(-1);
    ndpmax = disndp(-1);

d2105 3
a2107 3
        wcsnpv(npv[ialt]);
        wcsnps(nps[ialt]);
        if ((status = wcsini(1, alts[ialt], wcsp))) {
d2130 1
a2130 1
          disndp(ndp[ialt]);
d2132 1
a2132 1
          lindis(1, &(wcsp->lin), dis);
d2142 1
a2142 1
          disndp(ndq[ialt]);
d2144 1
a2144 1
          lindis(2, &(wcsp->lin), dis);
a2157 5
    /* Restore the original values of NPVMAX, NPSMAX, and NDPMAX. */
    wcsnpv(npvmax);
    wcsnps(npsmax);
    if (ndis) disndp(ndpmax);

d2321 1
a2321 1
    /* Decipher the core dump stored in the WATi_m strings. */
d2332 1
a2332 1
        lindis(2, &(wcsp->lin), 0x0);
@


5.17.1.1
log
@WCSLIB 5.17 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.17 2017/09/18 08:44:23 mcalabre Exp $
@


5.17.1.2
log
@Implemented as a reentrant scanner (with the same API) by means of a thin
wrapper over the original Flex scanner modified as required (with changed
API) to use the "reentrant" option.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.17.1.1 2017/09/18 08:45:59 mcalabre Exp mcalabre $
a73 1
%option reentrant
d136 2
a137 33
static int wcspih_scanner(char *header, int nkeyrec, int relax, int ctrl,
                          int *nreject, int *nwcs, struct wcsprm **wcs,
                          yyscan_t yyscanner);

/*--------------------------------------------------------------------------*/

int wcspih(
  char *header,
  int nkeyrec,
  int relax,
  int ctrl,
  int *nreject,
  int *nwcs,
  struct wcsprm **wcs)

{
  int status;
  yyscan_t yyscanner;
  int yylex_init(yyscan_t *yyscanner);
  int yylex_destroy(yyscan_t yyscanner);

  yylex_init(&yyscanner);
  status = wcspih_scanner(header, nkeyrec, relax, ctrl, nreject, nwcs, wcs,
                          yyscanner);
  yylex_destroy(yyscanner);

  return status;
}

/*--------------------------------------------------------------------------*/

#define YY_DECL int wcspih_scanner(char *header, int nkeyrec, int relax, \
 int ctrl, int *nreject, int *nwcs, struct wcsprm **wcs, yyscan_t yyscanner)
d188 1
d1894 1
d1935 1
a1935 1
	    yyrestart(yyin, yyscanner);
d1938 1
@


5.17.1.3
log
@Modified wcspih_inits() to use wcsinit() and lindist() in place of wcsini()
and lindis().
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.17.1.2 2017/12/05 01:38:46 mcalabre Exp mcalabre $
d2088 5
d2110 3
a2112 3
        npvmax = npv[ialt];
        npsmax = nps[ialt];
        if ((status = wcsinit(1, alts[ialt], wcsp, npvmax, npsmax, -1))) {
d2135 1
a2135 1
          ndpmax = ndp[ialt];
d2137 1
a2137 1
          lindist(1, &(wcsp->lin), dis, ndpmax);
d2147 1
a2147 1
          ndpmax = ndq[ialt];
d2149 1
a2149 1
          lindist(2, &(wcsp->lin), dis, ndpmax);
d2162 5
@


5.17.1.4
log
@In wcspih_final(), replaced a call to lindis() with lindist().
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.17.1.3 2017/12/05 07:48:29 mcalabre Exp mcalabre $
d2321 1
a2321 1
    /* Disassemble the core dump stored in the WATi_m strings. */
d2332 1
a2332 1
        lindist(2, &(wcsp->lin), 0x0, 0);
@


5.17.1.5
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2018, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 5.17.1.4 2017/12/05 21:22:25 mcalabre Exp mcalabre $
@


5.16
log
@WCSLIB 5.16
@
text
@d3 1
a3 1
  WCSLIB 5.16 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.15.1.2 2017/01/15 04:14:00 mcalabre Exp mcalabre $
d156 2
a157 2
int wcspih_final(int alts[], int ndp[], int ndq[], int distran,
        double dsstmp[], char *wat[], int *nwcs, struct wcsprm **wcs);
d1528 1
a1528 1
	    wcsutil_str2double(yytext, "%lf", &dbltmp);
d1616 1
a1616 1
	  wcsutil_str2double(yytext, "%lf", &dbltmp);
d1955 3
a1957 2
	    return wcspih_final(alts, ndp, ndq, distran, dsstmp, wat, nwcs,
	                        wcs);
a2207 1
  int alts[],
a2467 2

    free(wat[0]);
@


5.16.1.1
log
@WCSLIB 5.16 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.16 2017/01/15 04:25:01 mcalabre Exp $
@


5.16.1.2
log
@Fixed a memory leak relating to watstr - Pim Shellart email 2017-04-13.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.16.1.1 2017/01/15 04:28:59 mcalabre Exp mcalabre $
d1955 1
a1955 1
	    status = wcspih_final(alts, ndp, ndq, distran, dsstmp, wat, nwcs,
a1956 2
	    free(watstr);
	    return status;
d2468 2
@


5.16.1.3
log
@Removed the first, unused argument, alts[], from wcspih_final().
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.16.1.2 2017/09/12 12:42:37 mcalabre Exp mcalabre $
d156 2
a157 2
int wcspih_final(int ndp[], int ndq[], int distran, double dsstmp[],
        char *wat[], int *nwcs, struct wcsprm **wcs);
d1955 2
a1956 1
	    status = wcspih_final(ndp, ndq, distran, dsstmp, wat, nwcs, wcs);
d2209 1
@


5.16.1.4
log
@Revised argument list to wcsutil_str2double().
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.16.1.3 2017/09/12 14:20:01 mcalabre Exp mcalabre $
d1528 1
a1528 1
	    wcsutil_str2double(yytext, &dbltmp);
d1616 1
a1616 1
	  wcsutil_str2double(yytext, &dbltmp);
@


5.15
log
@WCSLIB 5.15
@
text
@d3 2
a4 2
  WCSLIB 5.15 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2016, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 5.14.1.1 2016/02/07 10:52:44 mcalabre Exp mcalabre $
@


5.15.1.1
log
@WCSLIB 5.15 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.15 2016/04/05 12:55:10 mcalabre Exp $
@


5.15.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2017, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 5.15.1.1 2016/04/05 12:58:35 mcalabre Exp mcalabre $
@


5.14
log
@WCSLIB 5.14
@
text
@d3 1
a3 1
  WCSLIB 5.14 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.13.1.1 2016/01/26 08:54:32 mcalabre Exp mcalabre $
@


5.14.1.1
log
@WCSLIB 5.14 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.14 2016/02/07 10:49:31 mcalabre Exp $
@


5.13
log
@WCSLIB 5.13
@
text
@d3 1
a3 1
  WCSLIB 5.13 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.12.1.3 2016/01/25 05:25:25 mcalabre Exp mcalabre $
@


5.13.1.1
log
@WCSLIB 5.13 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.13 2016/01/26 08:51:13 mcalabre Exp $
@


5.12
log
@WCSLIB 5.12
@
text
@d3 2
a4 2
  WCSLIB 5.12 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2015, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 5.11.1.1 2015/10/18 09:16:27 mcalabre Exp mcalabre $
d1021 1
a1021 1
	  /* DSS: plate identification. */
d1026 1
a1026 1
	  distran = DSS;
d1785 1
a1785 1
	        if (distran == 0) {
d1787 1
a1787 1
	            "valid WCS keyrecord.\n", keyrec, nvalid);
d1790 1
a1790 1
	            "recognised WCS convention.\n", keyrec, nvalid);
@


5.12.1.1
log
@WCSLIB 5.12 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.12 2015/11/15 02:13:00 mcalabre Exp $
@


5.12.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2016, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 5.12.1.1 2015/11/15 02:16:14 mcalabre Exp mcalabre $
@


5.12.1.3
log
@PLATEID by itself is now insufficient to trigger a DSS translation.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.12.1.2 2016/01/25 05:17:04 mcalabre Exp mcalabre $
d1021 1
a1021 1
	  /* DSS: plate identification (insufficient to trigger DSS). */
d1026 1
a1026 1
	  distran = 0;
d1785 1
a1785 1
	        if (distran || dssflag) {
d1787 1
a1787 1
	            "recognised WCS convention.\n", keyrec, nvalid);
d1790 1
a1790 1
	            "valid WCS keyrecord.\n", keyrec, nvalid);
@


5.11
log
@WCSLIB 5.11
@
text
@d3 1
a3 1
  WCSLIB 5.11 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.10.1.2 2015/10/18 08:57:50 mcalabre Exp mcalabre $
@


5.11.1.1
log
@WCSLIB 5.11 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.11 2015/10/18 09:13:05 mcalabre Exp $
@


5.10
log
@WCSLIB 5.10
@
text
@d3 1
a3 1
  WCSLIB 5.10 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.9.1.4 2015/10/09 07:03:52 mcalabre Exp mcalabre $
d2217 1
a2217 1
  char   field[8], *wp, wpoly[12], wtype[8];
@


5.10.1.1
log
@WCSLIB 5.10 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.10 2015/10/09 08:19:15 mcalabre Exp $
@


5.10.1.2
log
@Bug fix supplied by Ole Streicher: in wcspih_final(), char field[8] was
undersized, increase to char [16].
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.10.1.1 2015/10/09 08:22:35 mcalabre Exp mcalabre $
d2217 1
a2217 1
  char   field[16], *wp, wpoly[12], wtype[8];
@


5.9
log
@WCSLIB 5.9
@
text
@d3 1
a3 1
  WCSLIB 5.9 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.8.1.1 2015/07/08 11:07:18 mcalabre Exp mcalabre $
d1650 1
a1650 1
	          disp = wcsp->lin.dispre;
d1676 1
a1676 1
	              disp = wcsp->lin.disseq;
d1767 6
a1772 1
	            sprintf(keyword, "%.2s%d%c", keyname, i, a);
d2312 3
a2314 1
        return WCSHDRERR_PARSER;
@


5.9.1.1
log
@WCSLIB 5.9 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.9 2015/07/21 09:20:01 mcalabre Exp $
@


5.9.1.2
log
@Fixed buglet in <COMMENT>{INLINE}$ concerning construction of the dpkey
field name when a == ' '.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.9.1.1 2015/07/21 09:28:07 mcalabre Exp mcalabre $
d1767 1
a1767 6
	            if (a == ' ') {
	              sprintf(keyword, "%.2s%d", keyname, i);
	            } else {
	              sprintf(keyword, "%.2s%d%c", keyname, i, a);
	            }
	
@


5.9.1.3
log
@In wcspih_final(), allow unrecognised WAT projection types (tan, etc.) to
pass without returning an error.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.9.1.2 2015/08/23 08:27:12 mcalabre Exp mcalabre $
d2312 1
a2312 3
        /* Could contain "tan" or something else to be ignored. */
        lindis(2, &(wcsp->lin), 0x0);
        return 0;
@


5.9.1.4
log
@Fixed a bug triggered by SIP keywords in unconventional order, reported by
Colin Slater (LSST).
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.9.1.3 2015/09/15 09:26:25 mcalabre Exp mcalabre $
d1650 1
a1650 1
	          disp = (*wcs)->lin.dispre;
d1676 1
a1676 1
	              disp = (*wcs)->lin.disseq;
@


5.8
log
@WCSLIB 5.8
@
text
@d3 1
a3 1
  WCSLIB 5.8 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.7.1.4 2015/07/08 07:17:12 mcalabre Exp mcalabre $
@


5.8.1.1
log
@WCSLIB 5.8 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.8 2015/07/08 11:03:59 mcalabre Exp $
@


5.7
log
@WCSLIB 5.7
@
text
@d3 1
a3 1
  WCSLIB 5.7 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.6.1.2 2015/06/21 04:54:23 mcalabre Exp mcalabre $
d102 3
a104 4
%x CROTAi PROJPn SIP2 SIP3
%x CCCCCia CCia CCi_ja CCi_ma CCCCCCCa CCCCCCCC
%x VALUE
%x INTEGER_VAL FLOAT_VAL STRING_VAL
d129 7
d156 2
a157 2
int wcspih_final(int alts[], int ndp[], int ndq[], int dosip, int *nwcs,
        struct wcsprm **wcs);
d159 1
a159 1
        int ndp[], int ndq[], int dosip, int *nwcs, struct wcsprm **wcs);
d178 6
a183 6
	     keyword[16], strtmp[80];
	int  altlin, alts[27], distype, dosip, dpq[27], gotone, ialt, inttmp,
	     ipass, ipx, ix, jx, naxis, ndp[27], ndq[27], nother, *npptr,
	     nps[27], npass, npv[27], nvalid, rectype, sip, status, valtype,
	     voff;
	double dbltmp;
d231 5
a235 2
	sip     = 0;
	dosip   = 0;
d687 1
a687 1
	  distype = 1;
d696 1
a696 1
	  distype = 2;
d705 1
a705 1
	  distype = 1;
d715 1
a715 1
	  distype = 2;
d725 1
a725 1
	  distype = 1;
d734 1
a734 1
	  distype = 2;
d743 1
a743 1
	  distype = 1;
d753 1
a753 1
	  distype = 1;
d766 1
a766 1
	  distype = 1;
d779 1
a779 1
	  distype = 1;
d792 1
a792 1
	  distype = 1;
d805 1
a805 1
	  distype = 1;
d818 1
a818 1
	  distype = 1;
d831 1
a831 1
	  sip = 2;
d840 1
a840 1
	  sip = 2;
d849 1
a849 1
	  sip = 3;
d858 1
a858 1
	  sip = 3;
d864 203
a1244 29
<CROTAi>{Z1}{ALT}" " |
<CROTAi>{Z2}{ALT} |
<CROTAi>{Z3} {
	  a = ' ';
	  sscanf(yytext, "%d%c", &i, &a);
	
	  if (relax & WCSHDR_strict) {
	    errmsg = "the CROTAn keyword is deprecated, use PCi_ja";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_CROTAia) {
	    yyless(0);
	    BEGIN(CCCCCia);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "CROTAn keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<CROTAi>. {
	  yyless(0);
	  BEGIN(CCCCCia);
	}

d1352 29
d1416 1
a1416 1
	  distype = 1;
d1421 1
a1421 1
	  dosip = 1;
d1432 34
d1648 1
a1648 18
	        wcsp = *wcs + ialt;
	        if (distype == 0) {
	          voff = (char *)vptr - (char *)(&wcstem);
	          wptr = (void *)((char *)wcsp + voff);
	
	        } else {
	          voff = (char *)vptr - (char *)(&distem);
	          if (distype & 1) {
	            /* Prior distortion. */
	            disp = wcsp->lin.dispre;
	          } else {
	            /* Sequent distortion. */
	            disp = wcsp->lin.disseq;
	          }
	          wptr = (void *)((char *)disp + voff);
	        }
	
	        if (sip) {
d1650 1
d1655 2
a1656 1
	          sprintf(strtmp, "SIP.%s.%d_%d", (sip==2)?"FWD":"REV", p, q);
d1663 9
a1671 14
	        } else if (valtype == INTEGER) {
	          *((int *)wptr) = inttmp;
	
	        } else if (valtype == FLOAT) {
	          /* Apply keyword parameterization. */
	          if (npptr == npv) {
	            ipx = (wcsp->npv)++;
	            wcsp->pv[ipx].i = i;
	            wcsp->pv[ipx].m = m;
	            wptr = &(wcsp->pv[ipx].value);
	
	          } else if (j) {
	            wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis)
	                                      + (j - 1);
a1672 6
	          } else if (i) {
	            wptr = *((double **)wptr) + (i - 1);
	          }
	
	          if (special) {
	            special(wptr, dbltmp);
d1674 15
a1688 1
	            *((double *)wptr) = dbltmp;
d1691 3
a1693 5
	          /* Flag the presence of PCi_ja, or CDi_ja and/or CROTAia. */
	          if (altlin) {
	            wcsp->altlin |= altlin;
	            altlin = 0;
	          }
d1695 6
a1700 11
	        } else if (valtype == STRING) {
	          /* Apply keyword parameterization. */
	          if (npptr == nps) {
	            ipx = (wcsp->nps)++;
	            wcsp->ps[ipx].i = i;
	            wcsp->ps[ipx].m = m;
	            wptr = wcsp->ps[ipx].value;
	
	          } else if (j) {
	            wptr = *((char (**)[72])wptr) +
	                    (i - 1)*(wcsp->naxis) + (j - 1);
d1702 10
a1711 2
	          } else if (i) {
	            wptr = *((char (**)[72])wptr) + (i - 1);
d1714 2
a1715 2
	          cptr = (char *)wptr;
	          strcpy(cptr, strtmp);
d1717 54
a1770 6
	        } else if (valtype == RECORD) {
	          ipx = (disp->ndp)++;
	
	          sprintf(keyword, "%.2s%d%c", keyname, i, a);
	          dpfill(disp->dp+ipx, keyword, strtmp, i, rectype, inttmp,
	                 dbltmp);
d1780 7
a1786 3
	        wcsfprintf(stderr,
	          "%.80s\n  Accepted (%d) as a valid WCS keyrecord.\n",
	          keyrec, nvalid);
d1876 3
a1878 1
	  sip     = 0;
d1887 1
a1887 1
	                               dosip, nwcs, wcs)) ||
d1903 4
d1926 3
a1928 1
	    sip     = 0;
d1950 2
a1951 1
	    return wcspih_final(alts, ndp, ndq, dosip, nwcs, wcs);
d2025 1
a2025 1
  int dosip,
d2050 1
a2050 1
      return 2;
d2059 1
a2059 1
    if (dosip) {
d2063 4
d2095 1
a2095 1
            return 2;
d2107 1
a2107 1
            return 2;
d2134 4
a2137 2
    /* SIP distortion? */
    if (dosip) {
d2141 1
a2141 1
      /* SIP doesn't have alternates, nor axis mapping. */
d2145 9
d2205 4
a2208 2
  int dosip,
  int *nwcs,
d2212 6
a2217 1
  int ialt, status;
d2233 230
a2462 10
  /* SIP doesn't have alternates, nor axis mapping. */
  if (dosip) {
    dpfill((*wcs)->lin.dispre->dp+1, "DP1", "OFFSET.1",  0, 1, 0,
           (*wcs)->crpix[0]);
    dpfill((*wcs)->lin.dispre->dp+2, "DP1", "OFFSET.2",  0, 1, 0,
           (*wcs)->crpix[1]);
    dpfill((*wcs)->lin.dispre->dp+4, "DP2", "OFFSET.1",  0, 1, 0,
           (*wcs)->crpix[0]);
    dpfill((*wcs)->lin.dispre->dp+5, "DP2", "OFFSET.2",  0, 1, 0,
           (*wcs)->crpix[1]);
@


5.7.1.1
log
@WCSLIB 5.7 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.7 2015/06/29 02:44:16 mcalabre Exp $
@


5.7.1.2
log
@Added support for DSS coordinates.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.7.1.1 2015/06/29 02:47:24 mcalabre Exp mcalabre $
d102 1
a102 1
%x CROTAi PROJPn SIP2 SIP3 DSSAMDXY PLTDECSN
a129 6
#define PRIOR   1
#define SEQUENT 2

#define SIP     1
#define DSS     2

d150 2
a151 2
int wcspih_final(int alts[], int ndp[], int ndq[], int distran,
        double dsstmp[], int *nwcs, struct wcsprm **wcs);
d153 1
a153 1
        int ndp[], int ndq[], int distran, int *nwcs, struct wcsprm **wcs);
d173 5
a177 5
	int  altlin, alts[27], distran, distype, dpq[27], dssflag, gotone,
	     ialt, inttmp, ipass, ipx, ix, jx, naxis, ndp[27], ndq[27],
	     nother, *npptr, nps[27], npass, npv[27], nvalid, rectype,
	     sipflag, status, valtype, voff;
	double dbltmp, dsstmp[20];
d225 2
a226 3
	distran = 0;
	sipflag = 0;
	dssflag = 0;
d678 1
a678 1
	  distype = PRIOR;
d687 1
a687 1
	  distype = SEQUENT;
d696 1
a696 1
	  distype = PRIOR;
d706 1
a706 1
	  distype = SEQUENT;
d716 1
a716 1
	  distype = PRIOR;
d725 1
a725 1
	  distype = SEQUENT;
d734 1
a734 1
	  distype = PRIOR;
d744 1
a744 1
	  distype = PRIOR;
d757 1
a757 1
	  distype = PRIOR;
d770 1
a770 1
	  distype = PRIOR;
d783 1
a783 1
	  distype = PRIOR;
d796 1
a796 1
	  distype = PRIOR;
d809 1
a809 1
	  distype = PRIOR;
d822 1
a822 1
	  sipflag = 2;
d831 1
a831 1
	  sipflag = 2;
d840 1
a840 1
	  sipflag = 3;
d849 1
a849 1
	  sipflag = 3;
a854 174
^CNPIX1"  " {
	  /* DSS: LLH corner pixel coordinate 1. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "CNPIX1";
	  BEGIN(VALUE);
	}

^CNPIX2"  " {
	  /* DSS: LLH corner pixel coordinate 2. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+1;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "CNPIX1";
	  BEGIN(VALUE);
	}

^PPO3"    " {
	  /* DSS: plate centre x-coordinate in micron. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+2;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PPO3";
	  BEGIN(VALUE);
	}

^PPO6"    " {
	  /* DSS: plate centre y-coordinate in micron. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+3;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PPO6";
	  BEGIN(VALUE);
	}

^XPIXELSZ {
	  /* DSS: pixel x-dimension in micron. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+4;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "XPIXELSZ";
	  BEGIN(VALUE);
	}

^YPIXELSZ {
	  /* DSS: pixel y-dimension in micron. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+5;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "YPIXELSZ";
	  BEGIN(VALUE);
	}

^PLTRAH"  " {
	  /* DSS: plate centre, right ascension - hours. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+6;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTRAH";
	  BEGIN(VALUE);
	}

^PLTRAM"  " {
	  /* DSS: plate centre, right ascension - minutes. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+7;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTRAM";
	  BEGIN(VALUE);
	}

^PLTRAS"  " {
	  /* DSS: plate centre, right ascension - seconds. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+8;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTRAS";
	  BEGIN(VALUE);
	}

^PLTDECSN {
	  /* DSS: plate centre, declination - sign. */
	  valtype = STRING;
	  distype = SEQUENT;
	  vptr    = dsstmp+9;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTDECSN";
	  BEGIN(PLTDECSN);
	}

^PLTDECD" " {
	  /* DSS: plate centre, declination - degrees. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+10;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTDECD";
	  BEGIN(VALUE);
	}

^PLTDECM" " {
	  /* DSS: plate centre, declination - arcmin. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+11;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTDECM";
	  BEGIN(VALUE);
	}

^PLTDECS" " {
	  /* DSS: plate centre, declination - arcsec. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = dsstmp+12;
	  dssflag = 1;
	  distran = DSS;
	
	  keyname = "PLTDECS";
	  BEGIN(VALUE);
	}

^AMDX	{
	  /* DSS: axis 1 polynomial coefficient. */
	  i = 1;
	  dssflag = 2;
	
	  keyname = "AMDXm";
	  BEGIN(DSSAMDXY);
	}

^AMDY	{
	  /* DSS: axis 2 polynomial coefficient. */
	  i = 2;
	  dssflag = 2;
	
	  keyname = "AMDYm";
	  BEGIN(DSSAMDXY);
	}

d1204 1
a1204 1
	  distype = PRIOR;
d1209 1
a1209 1
	  distran = SIP;
a1219 34
<DSSAMDXY>{I1}"   " |
<DSSAMDXY>{I2}"  " {
	  /* DSS keywords. */
	  valtype = FLOAT;
	  distype = SEQUENT;
	  vptr    = &(distem.dp);
	  npptr   = ndq;
	
	  a = ' ';
	  distran = DSS;
	
	  sscanf(yytext, "%d", &m);
	  BEGIN(VALUE);
	}

<DSSAMDXY>. {
	  BEGIN(DISCARD);
	}

<PLTDECSN>=" "+{STRING} {
	  /* Special handling for this iconic DSS keyword. */
	  if (1 < ipass) {
	    /* Look for a minus sign. */
	    sscanf(yytext, "= '%s", strtmp);
	    dbltmp = strcmp(strtmp, "-") ? 1.0 : -1.0;
	  }
	
	  BEGIN(COMMENT);
	}

<PLTDECSN>. {
	  BEGIN(DISCARD);
	}

d1402 18
a1419 1
	        if (sipflag) {
a1420 1
	          disp = wcsp->lin.dispre;
d1425 1
a1425 2
	          sprintf(strtmp, "SIP.%s.%d_%d", (sipflag==2)?"FWD":"REV",
	                  p, q);
d1432 14
a1445 5
	        } else if (dssflag) {
	          /* All DSS keywords require special handling. */
	          if (dssflag == 1) {
	            /* Temporary parameter for DSS used by wcspih_final(). */
	            *((double *)vptr) = dbltmp;
d1447 6
d1454 7
a1460 15
	            /* Translate a DSS keyword into DQja. */
	            if (m <= 13 || dbltmp != 0.0) {
	              disp = wcsp->lin.disseq;
	              ipx = (disp->ndp)++;
	
	              /* DSS doesn't have alternates. */
	              sprintf(keyword, "DQ%d", i);
	              sprintf(strtmp, "AMD.%d", m);
	              dpfill(disp->dp+ipx, keyword, strtmp, i, 1, 0, dbltmp);
	
	              /* Also required by wcspih_final(). */
	              if (m <= 3) {
	                dsstmp[12+(i-1)*3+m] = dbltmp;
	              }
	            }
d1463 11
a1473 6
	        } else {
	          /* An ordinary keyword. */
	          wcsp = *wcs + ialt;
	          if (distype == 0) {
	            voff = (char *)vptr - (char *)(&wcstem);
	            wptr = (void *)((char *)wcsp + voff);
d1475 2
a1476 10
	          } else {
	            voff = (char *)vptr - (char *)(&distem);
	            if (distype == PRIOR) {
	              /* Prior distortion. */
	              disp = wcsp->lin.dispre;
	            } else {
	              /* Sequent distortion. */
	              disp = wcsp->lin.disseq;
	            }
	            wptr = (void *)((char *)disp + voff);
d1479 5
a1483 2
	          if (valtype == INTEGER) {
	            *((int *)wptr) = inttmp;
d1485 3
a1487 54
	          } else if (valtype == FLOAT) {
	            /* Apply keyword parameterization. */
	            if (npptr == npv) {
	              ipx = (wcsp->npv)++;
	              wcsp->pv[ipx].i = i;
	              wcsp->pv[ipx].m = m;
	              wptr = &(wcsp->pv[ipx].value);
	
	            } else if (j) {
	              wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis)
	                                        + (j - 1);
	
	            } else if (i) {
	              wptr = *((double **)wptr) + (i - 1);
	            }
	
	            if (special) {
	              special(wptr, dbltmp);
	            } else {
	              *((double *)wptr) = dbltmp;
	            }
	
	            /* Flag presence of PCi_ja, or CDi_ja and/or CROTAia. */
	            if (altlin) {
	              wcsp->altlin |= altlin;
	              altlin = 0;
	            }
	
	          } else if (valtype == STRING) {
	            /* Apply keyword parameterization. */
	            if (npptr == nps) {
	              ipx = (wcsp->nps)++;
	              wcsp->ps[ipx].i = i;
	              wcsp->ps[ipx].m = m;
	              wptr = wcsp->ps[ipx].value;
	
	            } else if (j) {
	              wptr = *((char (**)[72])wptr) +
	                      (i - 1)*(wcsp->naxis) + (j - 1);
	
	            } else if (i) {
	              wptr = *((char (**)[72])wptr) + (i - 1);
	            }
	
	            cptr = (char *)wptr;
	            strcpy(cptr, strtmp);
	
	          } else if (valtype == RECORD) {
	            ipx = (disp->ndp)++;
	
	            sprintf(keyword, "%.2s%d%c", keyname, i, a);
	            dpfill(disp->dp+ipx, keyword, strtmp, i, rectype, inttmp,
	                   dbltmp);
	          }
d1497 3
a1499 7
	        if (distran == 0) {
	          wcsfprintf(stderr, "%.80s\n  Accepted (%d) as a "
	            "valid WCS keyrecord.\n", keyrec, nvalid);
	        } else {
	          wcsfprintf(stderr, "%.80s\n  Accepted (%d) as a "
	            "recognised WCS convention.\n", keyrec, nvalid);
	        }
d1589 1
a1589 2
	  sipflag = 0;
	  dssflag = 0;
d1598 1
a1598 1
	                               distran, nwcs, wcs)) ||
d1633 1
a1633 2
	    sipflag = 0;
	    dssflag = 0;
d1655 1
a1655 1
	    return wcspih_final(alts, ndp, ndq, distran, dsstmp, nwcs, wcs);
d1729 1
a1729 1
  int distran,
d1763 1
a1763 1
    if (distran == SIP) {
a1766 4

    } else if (distran == DSS) {
      /* DPja.NAXES to be added for DSS (see below and wcspih_final()). */
      ndq[0] += 2;
d1834 2
a1835 4
    /* Translated distortion?  Neither SIP nor DSS have alternates, so the */
    /* presence of keywords for either (not both together), as flagged by  */
    /* distran, necessarily refers to the primary representation.          */
    if (distran == SIP) {
d1839 1
a1839 1
      /* SIP doesn't have axis mapping. */
a1842 9

    } else if (distran == DSS) {
      strcpy((*wcs)->lin.disseq->dtype[0], "DSS");
      strcpy((*wcs)->lin.disseq->dtype[1], "DSS");

      /* The Paper IV translation of DSS doesn't require an axis mapping. */
      (*wcs)->lin.disseq->ndp = 2;
      dpfill((*wcs)->lin.disseq->dp,   "DQ1", "NAXES",  0, 0, 2, 0.0);
      dpfill((*wcs)->lin.disseq->dp+1, "DQ2", "NAXES",  0, 0, 2, 0.0);
d1894 1
a1894 2
  int distran,
  double dsstmp[],
a1899 2
  double A1, A2, A3, B1, B2, B3, CNPIX1, CNPIX2, *crval, Rx, Ry, S, X0, Y0,
         Xc, Yc;
d1915 2
a1916 3
  /* Translated distortion functions. */
  if (distran == SIP) {
    /* SIP doesn't have alternates, nor axis mapping. */
a1924 48

  } else if (distran == DSS) {
    /* DSS doesn't have alternates, nor axis mapping.  This translation */
    /* follows Paper IV, Sect. 5.2 using the same variable names.       */
    CNPIX1 = dsstmp[0];
    CNPIX2 = dsstmp[1];

    Xc = dsstmp[2]/1000.0;
    Yc = dsstmp[3]/1000.0;
    Rx = dsstmp[4]/1000.0;
    Ry = dsstmp[5]/1000.0;

    A1 = dsstmp[13];
    A2 = dsstmp[14];
    A3 = dsstmp[15];
    B1 = dsstmp[16];
    B2 = dsstmp[17];
    B3 = dsstmp[18];
    S  = sqrt(fabs(A1*B1 - A2*B2));

    X0 = (A2*B3 - A3*B1) / (A1*B1 - A2*B2);
    Y0 = (A3*B2 - A1*B3) / (A1*B1 - A2*B2);

    (*wcs)->crpix[0] = (Xc - X0)/Rx - (CNPIX1 - 0.5);
    (*wcs)->crpix[1] = (Yc + Y0)/Ry - (CNPIX2 - 0.5);

    (*wcs)->pc[0] =  A1*Rx/S;
    (*wcs)->pc[1] = -A2*Ry/S;
    (*wcs)->pc[2] = -B2*Rx/S;
    (*wcs)->pc[3] =  B1*Ry/S;
    (*wcs)->altlin = 1;

    (*wcs)->cdelt[0] = -S/3600.0;
    (*wcs)->cdelt[1] =  S/3600.0;

    crval = (*wcs)->crval;
    crval[0] = (dsstmp[6]  + (dsstmp[7]  + dsstmp[8] /60.0)/60.0)*15.0;
    crval[1] =  dsstmp[10] + (dsstmp[11] + dsstmp[12]/60.0)/60.0;
    if (dsstmp[9] == -1.0) crval[1] *= -1.0;

    strcpy((*wcs)->ctype[0], "RA---TAN");
    strcpy((*wcs)->ctype[1], "DEC--TAN");

    /* Erase the approximate WCS provided in modern DSS headers. */
    (*wcs)->cd[0] = 0.0;
    (*wcs)->cd[1] = 0.0;
    (*wcs)->cd[2] = 0.0;
    (*wcs)->cd[3] = 0.0;
@


5.7.1.3
log
@Return the DSS PLATEID keyvalue in wcsprm::wcsname.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.7.1.2 2015/07/03 13:23:22 mcalabre Exp mcalabre $
a1017 12
^PLATEID" " {
	  /* DSS: plate identification. */
	  valtype = STRING;
	  distype = SEQUENT;
	  vptr    = dsstmp+13;
	  dssflag = 2;
	  distran = DSS;
	
	  keyname = "PLATEID";
	  BEGIN(VALUE);
	}

d1021 1
a1021 1
	  dssflag = 3;
d1030 1
a1030 1
	  dssflag = 3;
a1637 4
	          } else if (dssflag == 2) {
	            /* Temporary parameter for DSS used by wcspih_final(). */
	            strcpy((char *)vptr, strtmp);
	
d1639 1
a1639 1
	            /* Translate a DSS keyword into DQia. */
d1651 1
a1651 1
	                dsstmp[13+(i-1)*3+m] = dbltmp;
d2206 6
a2211 6
    A1 = dsstmp[14];
    A2 = dsstmp[15];
    A3 = dsstmp[16];
    B1 = dsstmp[17];
    B2 = dsstmp[18];
    B3 = dsstmp[19];
a2235 2

    sprintf((*wcs)->wcsname, "DSS PLATEID %.4s", (char *)(dsstmp+13));
@


5.7.1.4
log
@Added support for WAT distortions (TNX and ZPX).
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.7.1.3 2015/07/05 08:06:59 mcalabre Exp mcalabre $
a101 1
%x CCia CCi_ja CCCCCia CCi_ma CCCCCCCa CCCCCCCC
d103 3
a105 1
%x VALUE INTEGER_VAL FLOAT_VAL STRING_VAL
a134 1
#define WAT     3
d157 1
a157 1
        double dsstmp[], char *wat[], int *nwcs, struct wcsprm **wcs);
d178 1
a178 1
	     keyword[16], strtmp[80], *wat[2], *watstr;
d182 1
a182 1
	     sipflag, status, valtype, voff, watflag, watn;
a233 2
	watflag = 0;
	watn    = 0;
a1047 17
^WAT[12]_{Z3} {
	  /* TNX or ZPX: string-encoded data array. */
	  sscanf(yytext, "WAT%d_%d", &i, &m);
	  if (watn < m) watn = m;
	  watflag = 1;
	
	  valtype = STRING;
	  distype = SEQUENT;
	  vptr = wat[i-1] + 68*(m-1);
	
	  a = ' ';
	  distran = WAT;
	
	  keyname = "WATi_m";
	  BEGIN(VALUE);
	}

d1226 29
a1361 29
<CROTAi>{Z1}{ALT}" " |
<CROTAi>{Z2}{ALT} |
<CROTAi>{Z3} {
	  a = ' ';
	  sscanf(yytext, "%d%c", &i, &a);
	
	  if (relax & WCSHDR_strict) {
	    errmsg = "the CROTAn keyword is deprecated, use PCi_ja";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_CROTAia) {
	    yyless(0);
	    BEGIN(CCCCCia);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "CROTAn keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<CROTAi>. {
	  yyless(0);
	  BEGIN(CCCCCia);
	}

d1662 1
a1662 1
	              sprintf(strtmp, "DSS.AMD.%d", m);
a1671 4
	        } else if (watflag) {
	          /* String array for TNX and ZPX used by wcspih_final(). */
	          strcpy((char *)vptr, strtmp);
	
a1854 1
	  watflag = 0;
a1878 4
	
	    watstr = calloc(2*(watn*68 + 1), sizeof(char));
	    wat[0] = watstr;
	    wat[1] = watstr + watn*68 + 1;
a1899 1
	    watflag = 0;
d1921 1
a1921 2
	    return wcspih_final(alts, ndp, ndq, distran, dsstmp, wat, nwcs,
	                        wcs);
d2020 1
a2020 1
      return WCSHDRERR_MEMORY;
d2065 1
a2065 1
            return WCSHDRERR_MEMORY;
d2077 1
a2077 1
            return WCSHDRERR_MEMORY;
d2177 1
a2177 2
  char *wat[],
  int  *nwcs,
d2181 3
a2183 6
  char   field[8], *wp, wpoly[12], wtype[8];
  int    i, ialt, idp, ipv, m, npv, n, nterms, omax, omin, status, wctrl[4];
  double A1, A2, A3, B1, B2, B3, CNPIX1, CNPIX2, *crval, Rx, Ry, S, wval,
         X0, Y0, Xc, Yc;
  struct disprm *disp;
  struct wcsprm *wcsp;
d2199 1
a2199 2
  /* Translated distortion functions; apply only to the primary WCS. */
  wcsp = *wcs;
d2202 8
a2209 5
    disp = wcsp->lin.dispre;
    dpfill(disp->dp+1, "DP1", "OFFSET.1",  0, 1, 0, wcsp->crpix[0]);
    dpfill(disp->dp+2, "DP1", "OFFSET.2",  0, 1, 0, wcsp->crpix[1]);
    dpfill(disp->dp+4, "DP2", "OFFSET.1",  0, 1, 0, wcsp->crpix[0]);
    dpfill(disp->dp+5, "DP2", "OFFSET.2",  0, 1, 0, wcsp->crpix[1]);
d2233 2
a2234 2
    wcsp->crpix[0] = (Xc - X0)/Rx - (CNPIX1 - 0.5);
    wcsp->crpix[1] = (Yc + Y0)/Ry - (CNPIX2 - 0.5);
d2236 5
a2240 5
    wcsp->pc[0] =  A1*Rx/S;
    wcsp->pc[1] = -A2*Ry/S;
    wcsp->pc[2] = -B2*Rx/S;
    wcsp->pc[3] =  B1*Ry/S;
    wcsp->altlin = 1;
d2242 2
a2243 2
    wcsp->cdelt[0] = -S/3600.0;
    wcsp->cdelt[1] =  S/3600.0;
d2245 1
a2245 1
    crval = wcsp->crval;
d2250 2
a2251 2
    strcpy(wcsp->ctype[0], "RA---TAN");
    strcpy(wcsp->ctype[1], "DEC--TAN");
d2253 1
a2253 1
    sprintf(wcsp->wcsname, "DSS PLATEID %.4s", (char *)(dsstmp+13));
d2256 4
a2259 175
    wcsp->cd[0] = 0.0;
    wcsp->cd[1] = 0.0;
    wcsp->cd[2] = 0.0;
    wcsp->cd[3] = 0.0;

  } else if (distran == WAT) {
    /* TNX and ZPX don't have alternates, nor axis mapping. */
    disp = wcsp->lin.disseq;

    /* Decipher the core dump stored in the WATi_m strings. */
    nterms = 0;
    for (i = 0; i < 2; i++) {
      sscanf(wat[i], "wtype=%s", wtype);

      if (strcmp(wtype, "tnx") == 0) {
        strcpy(disp->dtype[i], "WAT-TNX");
      } else if (strcmp(wtype, "zpx") == 0) {
        strcpy(disp->dtype[i], "WAT-ZPX");
      } else {
        return WCSHDRERR_PARSER;
      }

      /* The PROJPn parameters are duplicated on each ZPX axis. */
      if (i == 1 && strcmp(wtype, "zpx") == 0) {
        /* Take those on the second (latitude) axis ignoring the other. */
        /* First we have to count them and allocate space in wcsprm.    */
        wp  = wat[i];
        for (npv = 0; npv < 30; npv++) {
          if ((wp = strstr(wp, "projp")) == 0x0) break;
          wp += 5;
        }

        /* Allocate space. */
        if (npv) {
          wcsp->npvmax += npv;
          wcsp->pv = realloc(wcsp->pv, wcsp->npvmax*sizeof(struct pvcard));
          if (wcsp->pv == 0x0) {
            return WCSHDRERR_MEMORY;
          }

          wcsp->m_pv = wcsp->pv;
        }

        /* Copy the values. */
        wp = wat[i];
        for (ipv = wcsp->npv; ipv < wcsp->npvmax; ipv++) {
          if ((wp = strstr(wp, "projp")) == 0x0) break;

          sscanf(wp, "projp%d=%lf", &m, &wval);
          wcsp->pv[ipv].i = 2;
          wcsp->pv[ipv].m = m;
          wcsp->pv[ipv].value = wval;

          wp += 5;
        }

        wcsp->npv += npv;
      }

      /* Read the control parameters. */
      if ((wp = strchr(wat[i], '"')) == 0x0) {
        return WCSHDRERR_PARSER;
      }
      wp++;

      for (m = 0; m < 4; m++) {
        sscanf(wp, "%d", wctrl+m);
        if ((wp = strchr(wp, ' ')) == 0x0) {
          return WCSHDRERR_PARSER;
        }
        wp++;
      }

      /* How many coefficients are we expecting? */
      omin = (wctrl[1] < wctrl[2]) ? wctrl[1] : wctrl[2];
      omax = (wctrl[1] < wctrl[2]) ? wctrl[2] : wctrl[1];
      if (wctrl[3] == 0) {
        /* No cross terms. */
        nterms += omin + omax;

      } else if (wctrl[3] == 1) {
        /* Full cross terms. */
        nterms += omin*omax;

      } else if (wctrl[3] == 2) {
        /* Half cross terms. */
        nterms += omin*omax - omin*(omin-1)/2;
      }
    }

    /* Allocate memory for dpkeys. */
    ndq[0] += 2*(1 + 1 + 4) + nterms;

    disp->ndpmax += ndq[0];
    disp->dp = realloc(disp->dp, disp->ndpmax*sizeof(struct dpkey));
    if (disp->dp == 0x0) {
      return WCSHDRERR_MEMORY;
    }

    disp->m_dp = disp->dp;


    /* Populate dpkeys. */
    idp = disp->ndp;
    for (i = 0; i < 2; i++) {
      dpfill(disp->dp+(idp++), "DQ", "NAXES", i+1, 0, 2, 0.0);

      /* Read the control parameters. */
      if ((wp = strchr(wat[i], '"')) == 0x0) {
        return WCSHDRERR_PARSER;
      }
      wp++;

      for (m = 0; m < 4; m++) {
        sscanf(wp, "%d", wctrl+m);
        if ((wp = strchr(wp, ' ')) == 0x0) {
          return WCSHDRERR_PARSER;
        }
        wp++;
      }

      /* Polynomial type. */
      dpfill(disp->dp+(idp++), "DQ", "WAT.POLY", i+1, 0, wctrl[0], 0.0);
      if (wctrl[0] == 1) {
        /* Chebyshev polynomial. */
        strcpy(wpoly, "CHBY");
      } else if (wctrl[0] == 2) {
        /* Legendre polynomial. */
        strcpy(wpoly, "LEGR");
      } else if (wctrl[0] == 3) {
        /* Polynomial is the sum of monomials. */
        strcpy(wpoly, "MONO");
      } else {
        /* Unknown code. */
        strcpy(wpoly, "UNKN");
      }

      /* Read the scaling parameters. */
      for (m = 0; m < 4; m++) {
        sscanf(wp, "%lf", &wval);
        sprintf(field, "WAT.%c%s", (m<2)?'X':'Y', (m%2)?"MAX":"MIN");
        dpfill(disp->dp+(idp++), "DQ", field, i+1, 1, 0, wval);

        if ((wp = strchr(wp, ' ')) == 0x0) {
          return WCSHDRERR_PARSER;
        }
        wp++;
      }

      /* Read the coefficients. */
      for (n = 0; n < wctrl[2]; n++) {
        for (m = 0; m < wctrl[1]; m++) {
          if (wctrl[3] == 0) {
            if (m && n) continue;
          } else if (wctrl[3] == 2) {
            if (m+n > omax-1) continue;
          }

          sscanf(wp, "%lf", &wval);
          if (wval == 0.0) continue;

          sprintf(field, "WAT.%s.%d_%d", wpoly, m, n);
          dpfill(disp->dp+(idp++), "DQ", field, i+1, 1, 0, wval);

          if ((wp = strchr(wp, ' ')) == 0x0) {
            return WCSHDRERR_PARSER;
          }
          wp++;
        }
      }
    }

    disp->ndp = idp;

    free(wat[0]);
@


5.6
log
@WCSLIB 5.6
@
text
@d3 1
a3 1
  WCSLIB 5.6 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.5.1.2 2015/06/06 08:43:34 mcalabre Exp mcalabre $
d676 1
a676 1
^CPDIS  {
d685 1
a685 1
^CQDIS {
d694 1
a694 1
^DP {
d704 1
a704 1
^DQ {
d714 1
a714 1
^CPERRja {
d723 1
a723 1
^CQERRia {
d732 1
a732 1
^DVERRa {
d737 1
a737 1
	  keyname = "CVERRa";
d819 1
a819 1
^A_ {
d823 1
a823 1

d828 1
a828 1
^B_ {
d832 1
a832 1

d837 1
a837 1
^AP_ {
d841 1
a841 1

d846 1
a846 1
^BP_ {
d850 1
a850 1

@


5.6.1.1
log
@WCSLIB 5.6 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.6 2015/06/14 07:11:24 mcalabre Exp $
@


5.6.1.2
log
@Fixed the rules for CPERRja, CQERRia, and DVERRa.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.6.1.1 2015/06/14 07:14:44 mcalabre Exp mcalabre $
d676 1
a676 1
^CPDIS	{
d685 1
a685 1
^CQDIS	{
d694 1
a694 1
^DP	{
d704 1
a704 1
^DQ	{
d714 1
a714 1
^CPERR	{
d723 1
a723 1
^CQERR	{
d732 1
a732 1
^DVERR	{
d737 1
a737 1
	  keyname = "DVERRa";
d819 1
a819 1
^A_	{
d823 1
a823 1
	
d828 1
a828 1
^B_	{
d832 1
a832 1
	
d837 1
a837 1
^AP_	{
d841 1
a841 1
	
d846 1
a846 1
^BP_	{
d850 1
a850 1
	
@


5.5
log
@WCSLIB 5.5
@
text
@d3 1
a3 1
  WCSLIB 5.5 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.4.1.2 2015/05/02 15:53:28 mcalabre Exp mcalabre $
d150 1
a150 1
int wcspih_final(int alts[], int ndp[], int ndq[], int *nwcs,
d1655 1
a1655 1
	    return wcspih_final(alts, ndp, ndq, nwcs, wcs);
d1672 1
a1672 1
  int distype, 
d1764 3
a1766 2
      /* DPja.NAXES to be added for SIP (see below). */
      ndp[0] += 2;
d1840 1
a1840 1
      (*wcs)->lin.dispre->ndp = 2;
d1842 1
a1842 1
      dpfill((*wcs)->lin.dispre->dp+1, "DP2", "NAXES",  0, 0, 2, 0.0);
d1894 1
d1913 12
@


5.5.1.1
log
@WCSLIB 5.5 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.5 2015/05/05 13:16:31 mcalabre Exp $
@


5.5.1.2
log
@The independent variables of the SIP polynomial are pixel coordinate offsets
from CRPIXja.  This is handled by conjuring up DPja.OFFSET.j appropriately
in wcspih_final().
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.5.1.1 2015/05/05 13:21:00 mcalabre Exp mcalabre $
d150 1
a150 1
int wcspih_final(int alts[], int ndp[], int ndq[], int dosip, int *nwcs,
d1655 1
a1655 1
	    return wcspih_final(alts, ndp, ndq, dosip, nwcs, wcs);
d1672 1
a1672 1
  int distype,
d1764 2
a1765 3
      /* DPja.NAXES and DPja.OFFSET.j to be added for SIP (see below and
         wcspih_final()). */
      ndp[0] += 6;
d1839 1
a1839 1
      (*wcs)->lin.dispre->ndp = 6;
d1841 1
a1841 1
      dpfill((*wcs)->lin.dispre->dp+3, "DP2", "NAXES",  0, 0, 2, 0.0);
a1892 1
  int dosip,
a1910 12
  }

  /* SIP doesn't have alternates, nor axis mapping. */
  if (dosip) {
    dpfill((*wcs)->lin.dispre->dp+1, "DP1", "OFFSET.1",  0, 1, 0,
           (*wcs)->crpix[0]);
    dpfill((*wcs)->lin.dispre->dp+2, "DP1", "OFFSET.2",  0, 1, 0,
           (*wcs)->crpix[1]);
    dpfill((*wcs)->lin.dispre->dp+4, "DP2", "OFFSET.1",  0, 1, 0,
           (*wcs)->crpix[0]);
    dpfill((*wcs)->lin.dispre->dp+5, "DP2", "OFFSET.2",  0, 1, 0,
           (*wcs)->crpix[1]);
@


5.4
log
@WCSLIB 5.4
@
text
@d3 1
a3 1
  WCSLIB 5.4 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.3.1.2 2015/04/21 13:51:54 mcalabre Exp mcalabre $
d911 5
d1582 1
@


5.4.1.1
log
@WCSLIB 5.4 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.4 2015/04/21 14:41:05 mcalabre Exp $
@


5.4.1.2
log
@Added a discard rule for <CCia>, needed for things like DQICORR.  Need to
reset distype when flushing a keyrecord.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.4.1.1 2015/04/21 14:44:28 mcalabre Exp mcalabre $
a910 5
<CCia>. {
	  /* Let it go. */
	  BEGIN(DISCARD);
	}

a1576 1
	  distype =  0;
@


5.3
log
@WCSLIB 5.3
@
text
@d3 1
a3 1
  WCSLIB 5.3 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.2.1.1 2015/04/15 12:39:14 mcalabre Exp mcalabre $
d80 2
d95 2
d102 2
a103 2
%x CROTAi PROJPn
%x CCCCCia CCi_ja CCi_ma CCCCCCCa CCCCCCCC
d106 1
a116 2
#include "wcs.h"
#include "wcshdr.h"
d121 4
d128 1
d150 1
a150 2
int wcspih_final(int alts[], int *nwcs, struct wcsprm **wcs);
int wcspih_inits(int naxis, int alts[], int npv[], int nps[], int *nwcs,
d152 4
a155 1
void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr);
d169 1
a169 1
	int  i, j, m;
d172 5
a176 4
	     strtmp[80];
	int  altlin, alts[27], gotone, ialt, inttmp, ipass, ipx, ix, jx,
	     naxis, nother, *npptr, nps[27], npass, npv[27], nvalid, status,
	     valtype, voff;
d179 1
d187 5
a191 2
	  npv[ialt] = 0;
	  nps[ialt] = 0;
d218 1
d225 2
d398 1
a398 1
	  npptr = npv;
d407 1
a407 1
	  npptr = npv;
d416 1
a416 1
	  npptr = nps;
d676 179
d869 2
d877 7
a883 2
<CCCCCia>0{I1}{ALT} |
<CCCCCia>00{I1} {
d896 8
a903 2
<CCCCCia>0{ALT}" " |
<CCCCCia>00{ALT} |
d1003 1
a1003 1
<CCi_ja>{Z1}{6} {
d1195 20
d1238 2
d1322 56
d1381 1
a1381 1
	    wcspih_naxes(naxis, i, j, a, alts, npptr);
d1398 15
a1412 2
	        voff = (char *)vptr - (char *)(&wcstem);
	        wptr = (void *)((char *)wcsp + voff);
d1414 14
a1427 1
	        if (valtype == INTEGER) {
d1476 7
d1583 1
d1591 2
a1592 1
	    if ((status = wcspih_inits(naxis, alts, npv, nps, nwcs, wcs)) ||
d1621 1
d1627 1
d1649 1
a1649 1
	    return wcspih_final(alts, nwcs, wcs);
d1657 2
a1658 2
* number of coordinate axes in each, and count the number of PVi_ma and
* PSi_ma keywords in each representation.
d1661 9
a1669 1
void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr)
d1700 4
d1718 1
d1721 3
d1728 1
a1728 1
  int ialt, defaults, npsmax, npvmax, status = 0;
d1730 1
d1741 1
a1741 1
    wcspih_naxes(naxis, 0, 0, ' ', alts, 0x0);
d1747 1
a1747 1
    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
d1751 1
a1751 1
    /* Record the current values of NPVMAX and NPSMAX. */
d1754 7
d1785 25
d1821 1
a1821 1
    /* Restore the original values of NPVMAX and NPSMAX. */
d1824 13
d1885 2
d1898 6
@


5.3.1.1
log
@WCSLIB 5.3 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.3 2015/04/21 02:50:51 mcalabre Exp $
@


5.3.1.2
log
@Now parses Paper IV distortion keywords (CPDISja, CQDISia, DPja, DQia,
etc.).  SIP keywords are also parsed and translated.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.3.1.1 2015/04/21 02:54:02 mcalabre Exp mcalabre $
a79 2
Z5	[0-9]{5}
Z6	[0-9]{6}
a92 2
RECORD	'[^']*'
FIELD	[a-zA-Z_][a-zA-Z_0-9.]*
d98 2
a99 2
%x CROTAi PROJPn SIP2 SIP3
%x CCCCCia CCia CCi_ja CCi_ma CCCCCCCa CCCCCCCC
a101 1
%x RECORD_VAL RECFIELD RECCOLON RECVALUE RECEND
d112 2
a117 4
#include "dis.h"
#include "wcs.h"
#include "wcshdr.h"

a120 1
#define RECORD  3
d142 2
a143 1
int wcspih_final(int alts[], int ndp[], int ndq[], int *nwcs,
d145 1
a145 4
int wcspih_inits(int naxis, int alts[], int dpq[], int npv[], int nps[],
        int ndp[], int ndq[], int dosip, int *nwcs, struct wcsprm **wcs);
void wcspih_naxes(int naxis, int i, int j, char a, int distype, int alts[],
        int dpq[], int *npptr);
d159 1
a159 1
	int  i, j, m, p, q;
d162 4
a165 5
	     keyword[16], strtmp[80];
	int  altlin, alts[27], distype, dosip, dpq[27], gotone, ialt, inttmp,
	     ipass, ipx, ix, jx, naxis, ndp[27], ndq[27], nother, *npptr,
	     nps[27], npass, npv[27], nvalid, rectype, sip, status, valtype,
	     voff;
a167 1
	struct disprm *disp, distem;
d175 2
a176 5
	  dpq[ialt]  = 0;
	  npv[ialt]  = 0;
	  nps[ialt]  = 0;
	  ndp[ialt]  = 0;
	  ndq[ialt]  = 0;
a202 1
	distype =  0;
a208 2
	sip     = 0;
	dosip   = 0;
d380 1
a380 1
	  npptr   = npv;
d389 1
a389 1
	  npptr   = npv;
d398 1
a398 1
	  npptr   = nps;
a657 179
^CPDIS  {
	  valtype = STRING;
	  distype = 1;
	  vptr    = &(distem.dtype);
	
	  keyname = "CPDISja";
	  BEGIN(CCCCCia);
	}

^CQDIS {
	  valtype = STRING;
	  distype = 2;
	  vptr    = &(distem.dtype);
	
	  keyname = "CQDISia";
	  BEGIN(CCCCCia);
	}

^DP {
	  valtype = RECORD;
	  distype = 1;
	  vptr    = &(distem.dp);
	  npptr   = ndp;
	
	  keyname = "DPja";
	  BEGIN(CCia);
	}

^DQ {
	  valtype = RECORD;
	  distype = 2;
	  vptr    = &(distem.dp);
	  npptr   = ndq;
	
	  keyname = "DQia";
	  BEGIN(CCia);
	}

^CPERRja {
	  valtype = FLOAT;
	  distype = 1;
	  vptr    = &(distem.maxdis);
	
	  keyname = "CPERRja";
	  BEGIN(CCCCCia);
	}

^CQERRia {
	  valtype = FLOAT;
	  distype = 2;
	  vptr    = &(distem.maxdis);
	
	  keyname = "CQERRia";
	  BEGIN(CCCCCia);
	}

^DVERRa {
	  valtype = FLOAT;
	  distype = 1;
	  vptr    = &(distem.totdis);
	
	  keyname = "CVERRa";
	  BEGIN(CCCCCCCa);
	}

^A_ORDER" " {
	  /* SIP: axis 1 polynomial degree (not stored). */
	  valtype = INTEGER;
	  distype = 1;
	  vptr    = 0x0;
	
	  i = 1;
	  a = ' ';
	
	  keyname = "A_ORDER";
	  BEGIN(VALUE);
	}

^B_ORDER" " {
	  /* SIP: axis 2 polynomial degree (not stored). */
	  valtype = INTEGER;
	  distype = 1;
	  vptr    = 0x0;
	
	  i = 2;
	  a = ' ';
	
	  keyname = "B_ORDER";
	  BEGIN(VALUE);
	}

^AP_ORDER {
	  /* SIP: axis 1 inverse polynomial degree (not stored). */
	  valtype = INTEGER;
	  distype = 1;
	  vptr    = 0x0;
	
	  i = 1;
	  a = ' ';
	
	  keyname = "AP_ORDER";
	  BEGIN(VALUE);
	}

^BP_ORDER {
	  /* SIP: axis 2 inverse polynomial degree (not stored). */
	  valtype = INTEGER;
	  distype = 1;
	  vptr    = 0x0;
	
	  i = 2;
	  a = ' ';
	
	  keyname = "BP_ORDER";
	  BEGIN(VALUE);
	}

^A_DMAX"  " {
	  /* SIP: axis 1 maximum distortion. */
	  valtype = FLOAT;
	  distype = 1;
	  vptr    = &(distem.maxdis);
	
	  i = 1;
	  a = ' ';
	
	  keyname = "A_DMAX";
	  BEGIN(VALUE);
	}

^B_DMAX"  " {
	  /* SIP: axis 2 maximum distortion. */
	  valtype = FLOAT;
	  distype = 1;
	  vptr    = &(distem.maxdis);
	
	  i = 2;
	  a = ' ';
	
	  keyname = "B_DMAX";
	  BEGIN(VALUE);
	}

^A_ {
	  /* SIP: axis 1 polynomial coefficient. */
	  i = 1;
	  sip = 2;

	  keyname = "A_p_q";
	  BEGIN(SIP2);
	}

^B_ {
	  /* SIP: axis 2 polynomial coefficient. */
	  i = 2;
	  sip = 2;

	  keyname = "B_p_q";
	  BEGIN(SIP2);
	}

^AP_ {
	  /* SIP: axis 1 inverse polynomial coefficient. */
	  i = 1;
	  sip = 3;

	  keyname = "AP_p_q";
	  BEGIN(SIP3);
	}

^BP_ {
	  /* SIP: axis 2 inverse polynomial coefficient. */
	  i = 2;
	  sip = 3;

	  keyname = "BP_p_q";
	  BEGIN(SIP3);
	}

a671 2
<CCia>{I1}{ALT}"    " |
<CCia>{I2}{ALT}"   "  |
d678 2
a679 7
<CCia>0{I1}{ALT}"   "    |
<CCia>0{Z1}{I1}{ALT}"  " |
<CCia>0{Z2}{I1}{ALT}" "  |
<CCia>0{Z3}{I1}{ALT}     |
<CCia>0{Z4}{I1}          |
<CCCCCia>0{I1}{ALT}      |
<CCCCCia>0{Z1}{I1} {
d692 2
a693 8
<CCia>{Z1}{ALT}"    " |
<CCia>{Z2}{ALT}"   "  |
<CCia>{Z3}{ALT}"  "   |
<CCia>{Z4}{ALT}" "    |
<CCia>{Z5}{ALT}       |
<CCia>{Z6}            |
<CCCCCia>{Z1}{ALT}" " |
<CCCCCia>{Z2}{ALT}    |
d793 1
a793 1
<CCi_ja>{Z2}{I1}{Z2}{I1} {
a984 20
<SIP2>{Z1}_{Z1}"   " |
<SIP3>{Z1}_{Z1}"  " {
	  /* SIP keywords. */
	  valtype = FLOAT;
	  distype = 1;
	  vptr    = &(distem.dp);
	  npptr   = ndp;
	
	  a = ' ';
	  dosip = 1;
	
	  sscanf(yytext, "%d_%d", &p, &q);
	  BEGIN(VALUE);
	}

<SIP2>. |
<SIP3>. {
	  BEGIN(DISCARD);
	}

a1007 2
	    } else if (valtype == RECORD) {
	      BEGIN(RECORD_VAL);
a1089 56
<RECORD_VAL>{RECORD} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
	
	  } else {
	    yyless(1);
	
	    BEGIN(RECFIELD);
	  }
	}

<RECORD_VAL>. {
	  errmsg = "a record was expected";
	  BEGIN(ERROR);
	}

<RECFIELD>{FIELD} {
	  strcpy(strtmp, yytext);
	  BEGIN(RECCOLON);
	}

<RECFIELD>. {
	  errmsg = "invalid record field";
	  BEGIN(ERROR);
	}

<RECCOLON>:" "+ {
	  BEGIN(RECVALUE);
	}

<RECCOLON>. {
	  errmsg = "invalid record syntax";
	  BEGIN(ERROR);
	}

<RECVALUE>{INTEGER} {
	  rectype = 0;
	  sscanf(yytext, "%d", &inttmp);
	  BEGIN(RECEND);
	}

<RECVALUE>{FLOAT} {
	  rectype = 1;
	  wcsutil_str2double(yytext, "%lf", &dbltmp);
	  BEGIN(RECEND);
	}

<RECVALUE>. {
	  errmsg = "invalid record value";
	  BEGIN(ERROR);
	}

<RECEND>' {
	  BEGIN(COMMENT);
	}

d1093 1
a1093 1
	    wcspih_naxes(naxis, i, j, a, distype, alts, dpq, npptr);
d1110 2
a1111 15
	        if (distype == 0) {
	          voff = (char *)vptr - (char *)(&wcstem);
	          wptr = (void *)((char *)wcsp + voff);
	
	        } else {
	          voff = (char *)vptr - (char *)(&distem);
	          if (distype & 1) {
	            /* Prior distortion. */
	            disp = wcsp->lin.dispre;
	          } else {
	            /* Sequent distortion. */
	            disp = wcsp->lin.disseq;
	          }
	          wptr = (void *)((char *)disp + voff);
	        }
d1113 1
a1113 14
	        if (sip) {
	          /* Translate a SIP keyword into DPja. */
	          ipx = (disp->ndp)++;
	
	          /* SIP doesn't have alternates. */
	          sprintf(keyword, "DP%d", i);
	          sprintf(strtmp, "SIP.%s.%d_%d", (sip==2)?"FWD":"REV", p, q);
	          if (valtype == INTEGER) {
	            dpfill(disp->dp+ipx, keyword, strtmp, i, 0, inttmp, 0.0);
	          } else {
	            dpfill(disp->dp+ipx, keyword, strtmp, i, 1, 0, dbltmp);
	          }
	
	        } else if (valtype == INTEGER) {
a1161 7
	
	        } else if (valtype == RECORD) {
	          ipx = (disp->ndp)++;
	
	          sprintf(keyword, "%.2s%d%c", keyname, i, a);
	          dpfill(disp->dp+ipx, keyword, strtmp, i, rectype, inttmp,
	                 dbltmp);
a1261 1
	  sip     = 0;
d1269 1
a1269 2
	    if ((status = wcspih_inits(naxis, alts, dpq, npv, nps, ndp, ndq,
	                               dosip, nwcs, wcs)) ||
a1297 1
	    distype =  0;
a1302 1
	    sip     = 0;
d1324 1
a1324 1
	    return wcspih_final(alts, ndp, ndq, nwcs, wcs);
d1332 2
a1333 2
* number of coordinate axes in each, which distortions are present, and the
* number of PVi_ma, PSi_ma, DPja, and DQia keywords in each representation.
d1336 1
a1336 9
void wcspih_naxes(
  int naxis,
  int i,
  int j,
  char a,
  int distype, 
  int alts[],
  int dpq[],
  int *npptr)
a1366 4
  /* Type of distortions present. */
  dpq[ialt] |= distype;

  /* Count PVi_ma, PSi_ma, DPja, or DQia keywords. */
a1380 1
  int dpq[],
a1382 3
  int ndp[],
  int ndq[],
  int dosip,
d1387 1
a1387 1
  int ialt, defaults, ndis, ndpmax, npsmax, npvmax, status = 0;
a1388 1
  struct disprm *dis;
d1399 1
a1399 1
    wcspih_naxes(naxis, 0, 0, ' ', 0, alts, dpq, 0x0);
d1405 1
a1405 1
    if ((*wcs = calloc(*nwcs, sizeof(struct wcsprm))) == 0x0) {
d1409 1
a1409 1
    /* Record the current values of NPVMAX, NPSMAX, and NDPMAX. */
a1411 7
    ndpmax = disndp(-1);

    ndis = 0;
    if (dosip) {
      /* DPja.NAXES to be added for SIP (see below). */
      ndp[0] += 2;
    }
a1435 25
        /* Any distortions present? */
        if (dpq[ialt] & 1) {
          if ((dis = calloc(1, sizeof(struct disprm))) == 0x0) {
            return 2;
          }

          /* Attach it to linprm.  Also inits it. */
          ndis++;
          disndp(ndp[ialt]);
          dis->flag = -1;
          lindis(1, &(wcsp->lin), dis);
        }

        if (dpq[ialt] & 2) {
          if ((dis = calloc(1, sizeof(struct disprm))) == 0x0) {
            return 2;
          }

          /* Attach it to linprm.  Also inits it. */
          ndis++;
          disndp(ndq[ialt]);
          dis->flag = -1;
          lindis(2, &(wcsp->lin), dis);
        }

d1447 1
a1447 1
    /* Restore the original values of NPVMAX, NPSMAX, and NDPMAX. */
a1449 13
    if (ndis) disndp(ndpmax);


    /* SIP distortion? */
    if (dosip) {
      strcpy((*wcs)->lin.dispre->dtype[0], "SIP");
      strcpy((*wcs)->lin.dispre->dtype[1], "SIP");

      /* SIP doesn't have alternates, nor axis mapping. */
      (*wcs)->lin.dispre->ndp = 2;
      dpfill((*wcs)->lin.dispre->dp,   "DP1", "NAXES",  0, 0, 2, 0.0);
      dpfill((*wcs)->lin.dispre->dp+1, "DP2", "NAXES",  0, 0, 2, 0.0);
    }
a1497 2
  int ndp[],
  int ndq[],
a1508 6
    }

    if (ndp[ialt] && ndq[ialt]) {
      /* Prior and sequent distortions co-exist in this representation;
         ensure the latter gets DVERRa. */
      (*wcs+ialt)->lin.disseq->totdis = (*wcs+ialt)->lin.dispre->totdis;
@


5.2
log
@WCSLIB 5.2
@
text
@d3 1
a3 1
  WCSLIB 5.2 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.1.1.1 2015/04/07 11:01:10 mcalabre Exp mcalabre $
@


5.2.1.1
log
@WCSLIB 5.2 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.2 2015/04/15 12:35:07 mcalabre Exp $
@


5.1
log
@WCSLIB 5.1
@
text
@d3 1
a3 1
  WCSLIB 5.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 5.0.1.1 2015/04/05 12:28:00 mcalabre Exp mcalabre $
@


5.1.1.1
log
@WCSLIB 5.1 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.1 2015/04/07 10:56:36 mcalabre Exp $
@


5.0
log
@WCSLIB 5.0
@
text
@d3 1
a3 1
  WCSLIB 5.0 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.25.1.4 2015/04/03 01:53:15 mcalabre Exp mcalabre $
@


5.0.1.1
log
@WCSLIB 5.0 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 5.0 2015/04/05 12:24:59 mcalabre Exp $
@


4.25
log
@WCSLIB 4.25
@
text
@d3 2
a4 2
  WCSLIB 4.25 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2014, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 4.24.1.1 2014/09/18 15:28:09 mcalabre Exp mcalabre $
d76 5
a80 1
I0	[0-9]
d91 1
a91 1
FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
d94 3
d142 1
a142 2
int wcspih_final(int alts[], double epoch[], double vsource[], int *nwcs,
        struct wcsprm **wcs);
d147 3
d161 6
a166 4
	char *cptr, *errmsg, errtxt[80], *hptr, *keep;
	int  altlin, alts[27], ialt, idx, ipx, ix, jx, naxis, *npptr,
	     nps[27], npv[27], pass, status, valtype, voff;
	double epoch[27], vsource[27];
d168 2
a169 1
	struct wcsprm *wcsp;
a176 2
	  epoch[ialt]   = UNDEFINED;
	  vsource[ialt] = UNDEFINED;
d184 1
d187 2
d190 5
d197 2
a198 1
	i = j = m = 0;
a202 1
	idx     = -1;
d206 3
a208 2
	altlin = 0;
	npptr  = 0x0;
d214 3
a216 1
	pass = 1;
d226 4
a229 2
^NAXIS"   = "" "*{INTEGER} {
	  if (pass == 1) {
d231 2
a232 1
	  }
a233 5
	  if (naxis < 0) {
	    errmsg = errtxt;
	    sprintf(errmsg, "Negative value of NAXIS ignored: %d", naxis);
	    naxis = 0;
	    BEGIN(ERROR);
d235 8
a242 1
	    BEGIN(DISCARD);
d247 12
a258 3
	  if (pass == 1) {
	    sscanf(yytext, "WCSAXES%c= %d", &a, &i);
	    wcspih_naxes(naxis, i, 0, a, alts, 0);
a259 1
	  BEGIN(FLUSH);
d264 3
a266 1
	  if (pass == 2) vptr = &((*wcs)->crpix);
d272 1
a272 1
	  if (pass == 2) vptr = &((*wcs)->pc);
d274 2
d281 1
a281 1
	  if (pass == 2) vptr = &((*wcs)->cd);
d283 2
d290 3
a292 1
	  if (pass == 2) vptr = &((*wcs)->cdelt);
d298 1
a298 1
	  if (pass == 2) vptr = &((*wcs)->crota);
d300 2
d307 3
a309 1
	  if (pass == 2) vptr = &((*wcs)->cunit);
d315 3
a317 1
	  if (pass == 2) vptr = &((*wcs)->ctype);
d323 3
a325 1
	  if (pass == 2) vptr = &((*wcs)->crval);
d331 3
a333 1
	  if (pass == 2) vptr = &((*wcs)->lonpole);
d339 3
a341 1
	  if (pass == 2) vptr = &((*wcs)->latpole);
d347 3
a349 1
	  if (pass == 2) vptr = &((*wcs)->restfrq);
d354 13
a366 4
	  valtype = FLOAT;
	  if (pass == 2) vptr = &((*wcs)->restfrq);
	  unput(' ');
	  BEGIN(CCCCCCCa);
d371 3
a373 1
	  if (pass == 2) vptr = &((*wcs)->restwav);
d379 1
a379 1
	  if (pass == 2) vptr = &((*wcs)->pv);
d381 2
d388 1
a388 1
	  if (pass == 2) vptr = &((*wcs)->pv);
d390 2
d397 1
a397 1
	  if (pass == 2) vptr = &((*wcs)->ps);
d399 2
d406 3
a408 1
	  if (pass == 2) vptr = &((*wcs)->cname);
d414 3
a416 1
	  if (pass == 2) vptr = &((*wcs)->crder);
d422 3
a424 1
	  if (pass == 2) vptr = &((*wcs)->csyer);
d430 4
a433 2
	  if (pass == 2) vptr = (*wcs)->dateavg;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d439 4
a442 2
	  if (pass == 2) vptr = (*wcs)->dateobs;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d449 5
a453 1
	  if (a == ' ' || relax & WCSHDR_EPOCHa) {
d455 4
a458 6
	    if (pass == 2) {
	      vptr = epoch;
	      if (a >= 'A') {
	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
	      }
	    }
d460 1
a460 1
	    unput(' ');
d474 3
a476 1
	  if (pass == 2) vptr = &((*wcs)->equinox);
d482 5
a486 2
	  if (pass == 2) vptr = &((*wcs)->mjdavg);
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d492 5
a496 2
	  if (pass == 2) vptr = &((*wcs)->mjdobs);
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d502 5
a506 2
	  if (pass == 2) vptr = (*wcs)->obsgeo;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d512 5
a516 2
	  if (pass == 2) vptr = (*wcs)->obsgeo + 1;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d522 5
a526 2
	  if (pass == 2) vptr = (*wcs)->obsgeo + 2;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d532 3
a534 1
	  if (pass == 2) vptr = (*wcs)->radesys;
d541 2
a542 1
	    if (pass == 2) vptr = (*wcs)->radesys;
d544 2
d549 1
a549 1
	    errmsg = "RADECSYS is non-standard, use RADESYSa";
d559 3
a561 1
	  if (pass == 2) vptr = (*wcs)->specsys;
d567 3
a569 1
	  if (pass == 2) vptr = (*wcs)->ssysobs;
d575 3
a577 1
	  if (pass == 2) vptr = (*wcs)->ssyssrc;
d583 3
a585 1
	  if (pass == 2) vptr = &((*wcs)->velangl);
d591 3
a593 1
	  if (pass == 2) vptr = &((*wcs)->velosys);
d600 5
a604 1
	  if (a == ' ' || relax & WCSHDR_VELREFa) {
d606 1
a606 1
	    if (pass == 2) vptr = &((*wcs)->velref);
d609 2
a622 2
	  sscanf(yytext, "VSOURCE%c", &a);
	
d625 4
a628 6
	    if (pass == 2) {
	      vptr = vsource;
	      if (a >= 'A') {
	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
	      }
	    }
d630 1
a630 1
	    unput(' ');
d634 1
a634 1
	    errmsg = "Deprecated VSOURCEa keyword rejected";
d644 3
a646 1
	  if (pass == 2) vptr = (*wcs)->wcsname;
d652 3
a654 1
	  if (pass == 2) vptr = &((*wcs)->zsource);
a658 1
	  yyless(0);
d661 1
a661 1
	    errmsg = "Keyrecords following the END keyrecord were ignored";
a674 1
	  idx = i - 1;
d678 21
a698 4
<CCCCCia>{I3} {
	  /* Invalid axis number will be caught by <VALUE>. */
	  sscanf(yytext, "%3d", &i);
	  BEGIN(VALUE);
d702 11
a712 1
	  BEGIN(DISCARD);
d720 34
a753 5
	  if (pass == 2) {
	    wcsp = *wcs;
	    if (a != ' ') {
	      wcsp += alts[a-'A'+1];
	    }
d755 3
a757 1
	    idx = (i-1)*(wcsp->naxis) + j - 1;
a758 1
	  BEGIN(VALUE);
d761 30
a790 9
<CCi_ja>{I1}_{I3}{ALT} |
<CCi_ja>{I3}_{I1}{ALT} |
<CCi_ja>{I1}_{I4} |
<CCi_ja>{I2}_{I3} |
<CCi_ja>{I3}_{I2} |
<CCi_ja>{I4}_{I1} {
	  /* Invalid axis numbers will be caught by <VALUE>. */
	  sscanf(yytext, "%d_%d", &i, &j);
	  BEGIN(VALUE);
d793 1
a793 1
<CCi_ja>{I0}{6} {
d795 2
a796 2
	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
a798 3
	    if (pass == 2) {
	      idx = (i-1)*((*wcs)->naxis) + j - 1;
	    }
d803 3
a805 2
	    sprintf(errmsg, "Defunct form of %si_ja keyword",
	                     (altlin==1) ? "PC" : "CD");
d809 1
d818 4
a821 2
<CROTAi>{I1}{ALT}" " |
<CROTAi>{I2}{ALT} {
d823 8
a830 3
	  if (a == ' ' || relax & WCSHDR_CROTAia) {
	    idx = i - 1;
	    BEGIN(VALUE);
d837 1
a841 7
<CROTAi>{I3} {
	  sscanf(yytext, "%d", &i);
	  a = ' ';
	  idx = i - 1;
	  BEGIN(VALUE);
	}

d843 2
a844 1
	  BEGIN(DISCARD);
a848 2
	  idx = -1;
	
d855 1
d860 11
a870 1
	  BEGIN(DISCARD);
d873 1
a873 1
<CCi_ma>{I1}_{I0}{ALT}"  " |
d875 1
a875 1
<CCi_ma>{I2}_{I0}{ALT}" " |
a877 1
	  idx = -1;
d881 67
a947 9
<CCi_ma>{I1}_{I3}{ALT} |
<CCi_ma>{I3}_{I0}{ALT} |
<CCi_ma>{I1}_{I4} |
<CCi_ma>{I2}_{I3} |
<CCi_ma>{I3}_{I2} |
<CCi_ma>{I4}_{I0} {
	  /* Invalid parameters will be caught by <VALUE>. */
	  sscanf(yytext, "%d_%d", &i, &m);
	  BEGIN(VALUE);
d954 1
a954 1
<PROJPn>{I0}"  " {
a958 1
	    idx = -1;
d962 12
a973 1
	    errmsg = "Defunct PROJPn keyword rejected";
d987 1
a987 1
	  if (i > 99 || j > 99 || m > 99) {
d989 2
a990 3
	      errmsg = errtxt;
	      if (i > 99 || j > 99) {
	        sprintf(errmsg, "Axis number exceeds 99");
d992 1
a992 1
	        sprintf(errmsg, "Parameter number exceeds 99");
d1010 1
a1010 1
	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
d1018 1
a1018 1
	  errmsg = "Invalid KEYWORD = VALUE syntax";
d1023 2
a1024 3
	  if (pass == 1) {
	    wcspih_naxes(naxis, i, j, a, alts, npptr);
	    BEGIN(FLUSH);
d1027 2
a1028 14
	    if (vptr) {
	      /* Determine the coordinate representation. */
	      for (ialt = 0; ialt < *nwcs; ialt++) {
	        /* The loop here is for keywords that apply */
	        /* to every alternate; these have a == 0. */
	        if (a >= 'A') {
	          ialt = alts[a-'A'+1];
	        }
	
	        wptr = vptr;
	        if (ialt) {
	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
	          wptr = (void *)((char *)vptr + voff);
	        }
d1030 1
a1030 17
	        /* Apply keyword parameterization. */
	        if (idx >= 0) {
	          wptr = *((int **)wptr) + idx;
	        }
	
	        /* Read the keyvalue. */
	        sscanf(yytext, "%d", (int *)wptr);
	
	        if (a) break;
	      }
	
	      BEGIN(COMMENT);
	
	    } else {
	      errmsg = "Internal parser ERROR, null int pointer";
	      BEGIN(ERROR);
	    }
d1035 1
a1035 1
	  errmsg = "An integer value was expected";
d1040 2
a1041 3
	  if (pass == 1) {
	    wcspih_naxes(naxis, i, j, a, alts, npptr);
	    BEGIN(FLUSH);
d1044 2
a1045 8
	    if (vptr) {
	      /* Determine the coordinate representation. */
	      for (ialt = 0; ialt < *nwcs; ialt++) {
	        /* The loop here is for keywords like MJD-OBS that */
	        /* apply to every alternate; these have a == 0.  */
	        if (a >= 'A') {
	          ialt = alts[a-'A'+1];
	        }
d1047 12
a1058 5
	        wptr = vptr;
	        if (ialt) {
	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
	          wptr = (void *)((char *)vptr + voff);
	        }
d1060 3
a1062 10
	        /* Apply keyword parameterization. */
	        if (idx >= 0) {
	          wptr = *((double **)wptr) + idx;
	
	        } else if (npptr == npv) {
	          ipx = (*wcs+ialt)->npv++;
	          (*wcs+ialt)->pv[ipx].i = i;
	          (*wcs+ialt)->pv[ipx].m = m;
	          wptr = &((*wcs+ialt)->pv[ipx].value);
	        }
d1064 6
a1069 2
	        /* Read the keyvalue. */
	        wcsutil_str2double(yytext, "%lf", (double *)wptr);
d1071 5
a1075 7
	        /* Flag the presence of PCi_ja, or CDi_ja and/or CROTAia. */
	        if (altlin) {
	          (*wcs+ialt)->altlin |= altlin;
	          altlin = 0;
	        }
	
	        if (a) break;
d1078 2
a1079 1
	      BEGIN(COMMENT);
d1081 1
a1081 4
	    } else {
	      errmsg = "Internal parser ERROR, null float pointer";
	      BEGIN(ERROR);
	    }
d1085 2
a1086 2
<FLOAT_VAL>. {
	  errmsg = "A floating-point value was expected";
d1090 3
a1092 2
<STRING_VAL>{STRING} {
	  if (pass == 1) {
d1096 31
a1126 9
	  } else {
	    if (vptr) {
	      /* Determine the coordinate representation. */
	      for (ialt = 0; ialt < *nwcs; ialt++) {
	        /* The loop here is for keywords like DATE-OBS that */
	        /* apply to every alternate; these have a == 0.   */
	        if (a >= 'A') {
	          ialt = alts[a-'A'+1];
	        }
d1128 3
a1130 5
	        wptr = vptr;
	        if (ialt) {
	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
	          wptr = (void *)((char *)vptr + voff);
	        }
d1132 5
a1136 10
	        /* Apply keyword parameterization. */
	        if (idx >= 0) {
	          wptr = *((char (**)[72])wptr) + idx;
	
	        } else if (npptr == nps) {
	          ipx = (*wcs+ialt)->nps++;
	          (*wcs+ialt)->ps[ipx].i = i;
	          (*wcs+ialt)->ps[ipx].m = m;
	          wptr = (*wcs+ialt)->ps[ipx].value;
	        }
d1138 4
a1141 9
	        /* Read the keyvalue. */
	        cptr = (char *)wptr;
	        strcpy(cptr, yytext+1);
	
	        /* Squeeze out repeated quotes. */
	        ix = 0;
	        for (jx = 0; jx < 72; jx++) {
	          if (ix < jx) {
	            cptr[ix] = cptr[jx];
d1144 14
a1157 5
	          if (cptr[jx] == '\0') {
	            if (ix) cptr[ix-1] = '\0';
	            break;
	          } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
	            jx++;
d1160 2
a1161 1
	          ix++;
d1163 4
d1168 6
a1173 1
	        if (a) break;
d1176 1
a1176 1
	      BEGIN(COMMENT);
d1179 1
a1179 1
	      errmsg = "Internal parser ERROR, null string pointer";
d1182 3
d1188 7
a1194 2
<STRING_VAL>. {
	  errmsg = "A string value was expected";
d1198 3
a1200 3
<COMMENT>" "*\/.* |
<COMMENT>" "* {
	  BEGIN(FLUSH);
d1203 2
a1204 2
<COMMENT>. {
	  errmsg = "Malformed keycomment";
d1208 2
a1209 2
<DISCARD>.* {
	  if (pass == 2) {
d1212 1
a1212 1
	      keep = wcspih_hdr - 80;
d1214 4
a1217 2
	    } else if (ctrl > 2) {
	      wcsfprintf(stderr, "%.80s\n  Discarded.\n", wcspih_hdr-80);
d1223 4
a1226 3
<ERROR>.* {
	  (*nreject)++;
	  if (pass == 2) {
d1229 1
a1229 1
	      keep = wcspih_hdr - 80;
d1232 3
a1234 3
	    if (abs(ctrl%10) > 1) {
	      wcsfprintf(stderr, "%.80s\n%4d: %s.\n", wcspih_hdr-80, *nreject,
	        errmsg);
d1241 1
a1241 1
	  if (pass == 2 && keep) {
d1248 3
a1250 1
	  i = j = m = 0;
d1252 3
d1256 7
a1262 3
	  keep = 0x0;
	  altlin = 0;
	  npptr = 0x0;
d1268 1
a1268 1
	  if (pass == 1) {
d1270 1
a1270 1
	         *nwcs == 0) {
d1275 1
a1275 1
	    if (abs(ctrl%10) > 2) {
d1285 1
d1287 1
d1290 1
d1293 2
a1294 2
	    pass = 2;
	    i = j = m = 0;
d1296 1
d1298 5
d1312 10
a1321 2
	      wcsfprintf(stderr, "%d WCS keyrecords were rejected.\n",
	        *nreject);
d1324 1
a1324 1
	    return wcspih_final(alts, epoch, vsource, nwcs, wcs);
d1440 4
d1457 36
a1497 2
  double epoch[],
  double vsource[],
a1502 1
  double beta, c = 299792458.0;
a1504 13
    /* Check for EPOCH overriding EQUINOXa. */
    if (undefined((*wcs+ialt)->equinox) && !undefined(epoch[ialt])) {
      /* Set EQUINOXa. */
      (*wcs+ialt)->equinox = epoch[ialt];
    }

    /* Check for VSOURCEa overriding ZSOURCEa. */
    if (undefined((*wcs+ialt)->zsource) && !undefined(vsource[ialt])) {
      /* Convert relativistic Doppler velocity to redshift. */
      beta = vsource[ialt]/c;
      (*wcs+ialt)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
    }

@


4.25.1.1
log
@WCSLIB 4.25 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.25 2014/12/14 14:29:36 mcalabre Exp $
@


4.25.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2015, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 4.25.1.1 2014/12/14 14:32:45 mcalabre Exp mcalabre $
@


4.25.1.3
log
@Significant development occasioned by the development of 'wcslint'.  Now
catches and reports more meaningfully on a wider class of syntax errors,
and with improved immunity to them.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.25.1.2 2015/01/06 01:01:06 mcalabre Exp mcalabre $
d76 1
a76 5
Z1	[0-9]
Z2	[0-9]{2}
Z3	[0-9]{3}
Z4	[0-9]{4}

d87 1
a87 1
FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eEdD][+-]?[0-9]+)?
a89 3
/* Inline comment syntax. */
INLINE " "*(\/.*)?

d135 2
a136 1
int wcspih_final(int alts[], int *nwcs, struct wcsprm **wcs);
a140 3
int wcspih_epoch(double *wptr, double epoch);
int wcspih_vsource(double *wptr, double vsource);

d152 4
a155 6
	char *cptr, *errmsg, errtxt[80], *hptr, *keep, *keyname, *keyrec,
	     strtmp[80];
	int  altlin, alts[27], gotone, ialt, inttmp, ipass, ipx, ix, jx,
	     naxis, nother, *npptr, nps[27], npass, npv[27], nvalid, status,
	     valtype, voff;
	double dbltmp;
d157 1
a157 2
	struct wcsprm *wcsp, wcstem;
	int (*special)(double *, double);
d165 2
a173 1
	keyrec = header;
a175 2
	
	/* For keeping tallies of keywords found. */
a176 5
	nvalid = 0;
	nother = 0;
	
	/* If strict, then also reject. */
	if (relax & WCSHDR_strict) relax |= WCSHDR_reject;
d179 1
a179 2
	i = j = 0;
	m = 0;
d184 1
d188 2
a189 3
	altlin  = 0;
	npptr   = 0x0;
	special = 0x0;
d195 1
a195 3
	/* Control variables. */
	ipass = 1;
	npass = 2;
d205 2
a206 4
^NAXIS"   = "" "*{INTEGER}{INLINE} {
	  keyname = "NAXISn";
	
	  if (ipass == 1) {
d208 1
a208 2
	    if (naxis < 0) naxis = 0;
	    BEGIN(FLUSH);
d210 5
d216 1
a216 8
	    sscanf(yytext, "NAXIS   = %d", &i);
	
	    if (i < 0) {
	      errmsg = "negative value of NAXIS ignored";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d221 3
a223 12
	  sscanf(yytext, "WCSAXES%c= %d", &a, &i);
	
	  if (i < 0) {
	    errmsg = "negative value of WCSAXESa ignored";
	    BEGIN(ERROR);
	
	  } else {
	    valtype = INTEGER;
	    vptr    = 0x0;
	
	    keyname = "WCSAXESa";
	    BEGIN(COMMENT);
d225 1
d230 1
a230 3
	  vptr    = &(wcstem.crpix);
	
	  keyname = "CRPIXja";
d236 1
a236 1
	  vptr    = &(wcstem.pc);
a237 2
	
	  keyname = "PCi_ja";
d243 1
a243 1
	  vptr    = &(wcstem.cd);
a244 2
	
	  keyname = "CDi_ja";
d250 1
a250 3
	  vptr    = &(wcstem.cdelt);
	
	  keyname = "CDELTia";
d256 1
a256 1
	  vptr    = &(wcstem.crota);
a257 2
	
	  keyname = "CROTAn";
d263 1
a263 3
	  vptr    = &(wcstem.cunit);
	
	  keyname = "CUNITia";
d269 1
a269 3
	  vptr    = &(wcstem.ctype);
	
	  keyname = "CTYPEia";
d275 1
a275 3
	  vptr    = &(wcstem.crval);
	
	  keyname = "CRVALia";
d281 1
a281 3
	  vptr    = &(wcstem.lonpole);
	
	  keyname = "LONPOLEa";
d287 1
a287 3
	  vptr    = &(wcstem.latpole);
	
	  keyname = "LATPOLEa";
d293 1
a293 3
	  vptr    = &(wcstem.restfrq);
	
	  keyname = "RESTFRQa";
d298 4
a301 13
	  if (relax & WCSHDR_strict) {
	    errmsg = "the RESTFREQ keyword is deprecated, use RESTFRQa";
	    BEGIN(ERROR);
	
	  } else {
	    valtype = FLOAT;
	    vptr    = &(wcstem.restfrq);
	
	    unput(' ');
	
	    keyname = "RESTFREQ";
	    BEGIN(CCCCCCCa);
	  }
d306 1
a306 3
	  vptr    = &(wcstem.restwav);
	
	  keyname = "RESTWAVa";
d312 1
a312 1
	  vptr    = &(wcstem.pv);
a313 2
	
	  keyname = "PVi_ma";
d319 1
a319 1
	  vptr    = &(wcstem.pv);
a320 2
	
	  keyname = "PROJPn";
d326 1
a326 1
	  vptr    = &(wcstem.ps);
a327 2
	
	  keyname = "PSi_ma";
d333 1
a333 3
	  vptr    = &(wcstem.cname);
	
	  keyname = "CNAMEia";
d339 1
a339 3
	  vptr    = &(wcstem.crder);
	
	  keyname = "CRDERia";
d345 1
a345 3
	  vptr    = &(wcstem.csyer);
	
	  keyname = "CSYERia";
d351 2
a352 4
	  vptr    = wcstem.dateavg;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-AVG";
d358 2
a359 4
	  vptr    = wcstem.dateobs;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-OBS";
d366 1
a366 5
	  if (relax & WCSHDR_strict) {
	    errmsg = "the EPOCH keyword is deprecated, use EQUINOXa";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_EPOCHa) {
d368 6
a373 2
	    vptr    = &(wcstem.equinox);
	    special = wcspih_epoch;
d375 1
a375 3
	    unput(a);
	
	    keyname = "EPOCH";
d389 1
a389 3
	  vptr    = &(wcstem.equinox);
	
	  keyname = "EQUINOXa";
d395 2
a396 5
	  vptr    = &(wcstem.mjdavg);
	
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "MJD-AVG";
d402 2
a403 5
	  vptr    = &(wcstem.mjdobs);
	
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "MJD-OBS";
d409 2
a410 5
	  vptr    = wcstem.obsgeo;
	
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-X";
d416 2
a417 5
	  vptr    = wcstem.obsgeo + 1;
	
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-Y";
d423 2
a424 5
	  vptr    = wcstem.obsgeo + 2;
	
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-Z";
d430 1
a430 3
	  vptr    = wcstem.radesys;
	
	  keyname = "RADESYSa";
d437 1
a437 2
	    vptr    = wcstem.radesys;
	
a438 2
	
	    keyname = "RADECSYS";
d442 1
a442 1
	    errmsg = "the RADECSYS keyword is deprecated, use RADESYSa";
d452 1
a452 3
	  vptr    = wcstem.specsys;
	
	  keyname = "SPECSYSa";
d458 1
a458 3
	  vptr    = wcstem.ssysobs;
	
	  keyname = "SSYSOBSa";
d464 1
a464 3
	  vptr    = wcstem.ssyssrc;
	
	  keyname = "SSYSSRCa";
d470 1
a470 3
	  vptr    = &(wcstem.velangl);
	
	  keyname = "VELANGLa";
d476 1
a476 3
	  vptr    = &(wcstem.velosys);
	
	  keyname = "VELOSYSa";
d483 1
a483 5
	  if (relax & WCSHDR_strict) {
	    errmsg = "the VELREF keyword is deprecated, use SPECSYSa";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_VELREFa) {
d485 1
a485 1
	    vptr    = &(wcstem.velref);
a487 2
	
	    keyname = "VELREF";
d500 2
d504 6
a509 2
	    vptr    = &(wcstem.zsource);
	    special = wcspih_vsource;
d511 1
a511 3
	    yyless(7);
	
	    keyname = "VSOURCEa";
d515 1
a515 1
	    errmsg = "the VSOURCEa keyword is deprecated, use ZSOURCEa";
d525 1
a525 3
	  vptr    = wcstem.wcsname;
	
	  keyname = "WCSNAMEa";
d531 1
a531 3
	  vptr    = &(wcstem.zsource);
	
	  keyname = "ZSOURCEa";
d536 1
d539 1
a539 1
	    errmsg = "keyrecords following the END keyrecord were ignored";
d553 1
d557 4
a560 21
<CCCCCia>0{I1}{ALT} |
<CCCCCia>00{I1} {
	  if (relax & WCSHDR_reject) {
	    /* Violates the basic FITS standard. */
	    errmsg = "indices in parameterised keywords must not have "
	             "leading zeroes";
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<CCCCCia>0{ALT}" " |
<CCCCCia>00{ALT} |
<CCCCCia>{Z3} {
	  /* Anything that has fallen through to this point must contain */
	  /* an invalid axis number. */
	  errmsg = "axis number must exceed 0";
	  BEGIN(ERROR);
d564 1
a564 11
	  if (relax & WCSHDR_reject) {
	    /* Looks too much like a FITS WCS keyword not to flag it. */
	    errmsg = errtxt;
	    sprintf(errmsg, "keyword looks very much like %s but isn't",
	      keyname);
	    BEGIN(ERROR);
	
	  } else {
	    /* Let it go. */
	    BEGIN(DISCARD);
	  }
d572 5
a576 29
	  BEGIN(VALUE);
	}


<CCi_ja>0{I1}_{I1}{ALT}" " |
<CCi_ja>{I1}_0{I1}{ALT}" " |
<CCi_ja>00{I1}_{I1}{ALT} |
<CCi_ja>0{I1}_0{I1}{ALT} |
<CCi_ja>{I1}_00{I1}{ALT} |
<CCi_ja>000{I1}_{I1} |
<CCi_ja>00{I1}_0{I1} |
<CCi_ja>0{I1}_00{I1} |
<CCi_ja>{I1}_000{I1} |
<CCi_ja>0{I1}_{I2}{ALT} |
<CCi_ja>{I1}_0{I2}{ALT} |
<CCi_ja>00{I1}_{I2} |
<CCi_ja>0{I1}_0{I2} |
<CCi_ja>{I1}_00{I2} |
<CCi_ja>0{I2}_{I1}{ALT} |
<CCi_ja>{I2}_0{I1}{ALT} |
<CCi_ja>00{I2}_{I1} |
<CCi_ja>0{I2}_0{I1} |
<CCi_ja>{I2}_00{I1} |
<CCi_ja>0{I2}_{I2} |
<CCi_ja>{I2}_0{I2} {
	  if (((altlin == 1) && (relax & WCSHDR_PC0i_0ja)) ||
	      ((altlin == 2) && (relax & WCSHDR_CD0i_0ja))) {
	    sscanf(yytext, "%d_%d%c", &i, &j, &a);
	    BEGIN(VALUE);
d578 1
a578 8
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "indices in parameterised keywords must not have "
	             "leading zeroes";
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
d580 1
d583 9
a591 30
<CCi_ja>{Z1}_{Z1}{ALT}"  " |
<CCi_ja>{Z2}_{Z1}{ALT}" " |
<CCi_ja>{Z1}_{Z2}{ALT}" " |
<CCi_ja>{Z3}_{Z1}{ALT} |
<CCi_ja>{Z2}_{Z2}{ALT} |
<CCi_ja>{Z1}_{Z3}{ALT} |
<CCi_ja>{Z4}_{Z1} |
<CCi_ja>{Z3}_{Z2} |
<CCi_ja>{Z2}_{Z3} |
<CCi_ja>{Z1}_{Z4} {
	  /* Anything that has fallen through to this point must contain */
	  /* an invalid axis number. */
	  errmsg = "axis number must exceed 0";
	  BEGIN(ERROR);
	}

<CCi_ja>{Z1}-{Z1}{ALT}"  " |
<CCi_ja>{Z2}-{Z1}{ALT}" " |
<CCi_ja>{Z1}-{Z2}{ALT}" " |
<CCi_ja>{Z3}-{Z1}{ALT} |
<CCi_ja>{Z2}-{Z2}{ALT} |
<CCi_ja>{Z1}-{Z3}{ALT} |
<CCi_ja>{Z4}-{Z1} |
<CCi_ja>{Z3}-{Z2} |
<CCi_ja>{Z2}-{Z3} |
<CCi_ja>{Z1}-{Z4} {
	  errmsg = errtxt;
	  sprintf(errmsg, "%s keyword must use an underscore, not a dash",
	    keyname);
	  BEGIN(ERROR);
d594 1
a594 1
<CCi_ja>{Z1}{6} {
d596 2
a597 2
	  if (((altlin == 1) && (relax & WCSHDR_PC00i00j)) ||
	      ((altlin == 2) && (relax & WCSHDR_CD00i00j))) {
d600 3
d607 2
a608 3
	    sprintf(errmsg,
	      "this form of the %s keyword is deprecated, use %s",
	      keyname, keyname);
a611 1
	    /* Pretend we don't recognize it. */
d620 2
a621 4
<CROTAi>{Z1}{ALT}" " |
<CROTAi>{Z2}{ALT} |
<CROTAi>{Z3} {
	  a = ' ';
d623 3
a625 8
	
	  if (relax & WCSHDR_strict) {
	    errmsg = "the CROTAn keyword is deprecated, use PCi_ja";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || relax & WCSHDR_CROTAia) {
	    yyless(0);
	    BEGIN(CCCCCia);
a631 1
	    /* Pretend we don't recognize it. */
d636 7
d644 1
a644 2
	  yyless(0);
	  BEGIN(CCCCCia);
d649 2
a656 1
	
d661 1
a661 11
	  if (relax & WCSHDR_reject) {
	    /* Looks too much like a FITS WCS keyword not to flag it. */
	    errmsg = errtxt;
	    sprintf(errmsg, "invalid alternate code, keyword resembles %s "
	      "but isn't", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
d664 1
a664 1
<CCi_ma>{I1}_{Z1}{ALT}"  " |
d666 1
a666 1
<CCi_ma>{I2}_{Z1}{ALT}" " |
d669 1
d673 9
a681 67
<CCi_ma>0{I1}_{Z1}{ALT}" " |
<CCi_ma>{I1}_0{Z1}{ALT}" " |
<CCi_ma>00{I1}_{Z1}{ALT} |
<CCi_ma>0{I1}_0{Z1}{ALT} |
<CCi_ma>{I1}_00{Z1}{ALT} |
<CCi_ma>000{I1}_{Z1} |
<CCi_ma>00{I1}_0{Z1} |
<CCi_ma>0{I1}_00{Z1} |
<CCi_ma>{I1}_000{Z1} |
<CCi_ma>0{I1}_{I2}{ALT} |
<CCi_ma>{I1}_0{I2}{ALT} |
<CCi_ma>00{I1}_{I2} |
<CCi_ma>0{I1}_0{I2} |
<CCi_ma>{I1}_00{I2} |
<CCi_ma>0{I2}_{Z1}{ALT} |
<CCi_ma>{I2}_0{Z1}{ALT} |
<CCi_ma>00{I2}_{Z1} |
<CCi_ma>0{I2}_0{Z1} |
<CCi_ma>{I2}_00{Z1} |
<CCi_ma>0{I2}_{I2} |
<CCi_ma>{I2}_0{I2} {
	  if (((valtype == FLOAT)  && (relax & WCSHDR_PV0i_0ma)) ||
	      ((valtype == STRING) && (relax & WCSHDR_PS0i_0ma))) {
	    sscanf(yytext, "%d_%d%c", &i, &m, &a);
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "indices in parameterised keywords must not have "
	             "leading zeroes";
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<CCi_ma>{Z1}_{Z1}{ALT}"  " |
<CCi_ma>{Z2}_{Z1}{ALT}" " |
<CCi_ma>{Z1}_{Z2}{ALT}" " |
<CCi_ma>{Z3}_{Z1}{ALT} |
<CCi_ma>{Z2}_{Z2}{ALT} |
<CCi_ma>{Z1}_{Z3}{ALT} |
<CCi_ma>{Z4}_{Z1} |
<CCi_ma>{Z3}_{Z2} |
<CCi_ma>{Z2}_{Z3} |
<CCi_ma>{Z1}_{Z4} {
	  /* Anything that has fallen through to this point must contain */
	  /* an invalid axis number. */
	  errmsg = "axis number must exceed 0";
	  BEGIN(ERROR);
	}

<CCi_ma>{Z1}-{Z1}{ALT}"  " |
<CCi_ma>{Z2}-{Z1}{ALT}" " |
<CCi_ma>{Z1}-{Z2}{ALT}" " |
<CCi_ma>{Z3}-{Z1}{ALT} |
<CCi_ma>{Z2}-{Z2}{ALT} |
<CCi_ma>{Z1}-{Z3}{ALT} |
<CCi_ma>{Z4}-{Z1} |
<CCi_ma>{Z3}-{Z2} |
<CCi_ma>{Z2}-{Z3} |
<CCi_ma>{Z1}-{Z4} {
	  errmsg = errtxt;
	  sprintf(errmsg, "%s keyword must use an underscore, not a dash",
	    keyname);
	  BEGIN(ERROR);
d688 1
a688 1
<PROJPn>{Z1}"  " {
d693 1
d697 1
a697 12
	    errmsg = "the PROJPn keyword is deprecated, use PVi_ma";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

<PROJPn>{Z2}" " |
<PROJPn>{Z3} {
	  if (relax & (WCSHDR_PROJPn | WCSHDR_reject)) {
	    errmsg = "invalid PROJPn keyword";
d711 1
a711 1
	  if (99 < i || 99 < j || 99 < m) {
d713 3
a715 2
	      if (99 < i || 99 < j) {
	        errmsg = "axis number exceeds 99";
d717 1
a717 1
	        errmsg = "parameter number exceeds 99";
d735 1
a735 1
	      sprintf(errmsg, "internal parser ERROR, bad data type: %d",
d743 1
a743 1
	  errmsg = "invalid KEYWORD = VALUE syntax";
d748 3
a750 2
	  if (ipass == 1) {
	    BEGIN(COMMENT);
d753 14
a766 3
	    /* Read the keyvalue. */
	    sscanf(yytext, "%d", &inttmp);
	    
d768 17
a784 1
	    BEGIN(COMMENT);
d789 1
a789 1
	  errmsg = "an integer value was expected";
d794 3
a796 2
	  if (ipass == 1) {
	    BEGIN(COMMENT);
d799 25
a823 2
	    /* Read the keyvalue. */
	    wcsutil_str2double(yytext, "%lf", &dbltmp);
d825 2
a826 12
	    BEGIN(COMMENT);
	  }
	}

<FLOAT_VAL>. {
	  errmsg = "a floating-point value was expected";
	  BEGIN(ERROR);
	}

<STRING_VAL>{STRING} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
d828 5
a832 3
	  } else {
	    /* Read the keyvalue. */
	    strcpy(strtmp, yytext+1);
d834 1
a834 5
	    /* Squeeze out repeated quotes. */
	    ix = 0;
	    for (jx = 0; jx < 72; jx++) {
	      if (ix < jx) {
	        strtmp[ix] = strtmp[jx];
d837 1
a837 6
	      if (strtmp[jx] == '\0') {
	        if (ix) strtmp[ix-1] = '\0';
	        break;
	      } else if (strtmp[jx] == '\'' && strtmp[jx+1] == '\'') {
	        jx++;
	      }
d839 3
a841 1
	      ix++;
a842 2
	
	    BEGIN(COMMENT);
d846 2
a847 2
<STRING_VAL>. {
	  errmsg = "a string value was expected";
d851 2
a852 3
<COMMENT>{INLINE}$ {
	  if (ipass == 1) {
	    /* Do first-pass bookkeeping. */
d856 9
a864 11
	  } else if (*wcs) {
	    /* Store the value now that the keyrecord has been validated. */
	    gotone = 0;
	    for (ialt = 0; ialt < *nwcs; ialt++) {
	      /* The loop here is for keywords that apply */
	      /* to every alternate; these have a == 0. */
	      if (a >= 'A') {
	        ialt = alts[a-'A'+1];
	        if (ialt < 0) break;
	      }
	      gotone = 1;
d866 5
a870 19
	      if (vptr) {
	        wcsp = *wcs + ialt;
	        voff = (char *)vptr - (char *)(&wcstem);
	        wptr = (void *)((char *)wcsp + voff);
	
	        if (valtype == INTEGER) {
	          *((int *)wptr) = inttmp;
	
	        } else if (valtype == FLOAT) {
	          /* Apply keyword parameterization. */
	          if (npptr == npv) {
	            ipx = (wcsp->npv)++;
	            wcsp->pv[ipx].i = i;
	            wcsp->pv[ipx].m = m;
	            wptr = &(wcsp->pv[ipx].value);
	
	          } else if (j) {
	            wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis)
	                                      + (j - 1);
d872 10
a881 9
	          } else if (i) {
	            wptr = *((double **)wptr) + (i - 1);
	          }
	
	          if (special) {
	            special(wptr, dbltmp);
	          } else {
	            *((double *)wptr) = dbltmp;
	          }
d883 9
a891 4
	          /* Flag the presence of PCi_ja, or CDi_ja and/or CROTAia. */
	          if (altlin) {
	            wcsp->altlin |= altlin;
	            altlin = 0;
d894 5
a898 14
	        } else if (valtype == STRING) {
	          /* Apply keyword parameterization. */
	          if (npptr == nps) {
	            ipx = (wcsp->nps)++;
	            wcsp->ps[ipx].i = i;
	            wcsp->ps[ipx].m = m;
	            wptr = wcsp->ps[ipx].value;
	
	          } else if (j) {
	            wptr = *((char (**)[72])wptr) +
	                    (i - 1)*(wcsp->naxis) + (j - 1);
	
	          } else if (i) {
	            wptr = *((char (**)[72])wptr) + (i - 1);
d901 1
a901 2
	          cptr = (char *)wptr;
	          strcpy(cptr, strtmp);
a902 4
	      }
	
	      if (a) break;
	    }
d904 1
a904 6
	    if (gotone) {
	      nvalid++;
	      if (ctrl == 4) {
	        wcsfprintf(stderr,
	          "%.80s\n  Accepted (%d) as a valid WCS keyrecord.\n",
	          keyrec, nvalid);
d907 1
a907 1
	      BEGIN(FLUSH);
d910 1
a910 1
	      errmsg = "syntactically valid WCS keyrecord has no effect";
a912 3
	
	  } else {
	    BEGIN(FLUSH);
d916 2
a917 2
<COMMENT>.*" "*\/.*$ {
	  errmsg = "invalid keyvalue";
d921 3
a923 8
<COMMENT>[^ \/\n]*{INLINE}$ {
	  errmsg = "invalid keyvalue";
	  BEGIN(ERROR);
	}

<COMMENT>" "+[^\/\n].*{INLINE}$ {
	  errmsg = "invalid keyvalue or malformed keycomment";
	  BEGIN(ERROR);
d926 2
a927 2
<COMMENT>.*$ {
	  errmsg = "malformed keycomment";
d931 2
a932 2
<DISCARD>.*$ {
	  if (ipass == npass) {
d935 1
a935 1
	      keep = keyrec;
d937 2
a938 4
	    } else if (2 < ctrl) {
	      nother++;
	      wcsfprintf(stderr, "%.80s\n  Not a recognised WCS keyword.\n",
	        keyrec);
d944 3
a946 4
<ERROR>.*$ {
	  if (ipass == npass) {
	    (*nreject)++;
	
d949 1
a949 1
	      keep = keyrec;
d952 3
a954 3
	    if (1 < abs(ctrl%10)) {
	      wcsfprintf(stderr, "%.80s\n  Rejected (%d), %s.\n",
	        keyrec, *nreject, errmsg);
d961 1
a961 1
	  if (ipass == npass && keep) {
d968 1
a968 3
	  /* Throw away the rest of the line and reset for the next one. */
	  i = j = 0;
	  m = 0;
a969 3
	
	  keyrec += 80;
	
d971 3
a973 7
	  vptr    = 0x0;
	  keep    = 0x0;
	
	  altlin  = 0;
	  npptr   = 0x0;
	  special = 0x0;
	
d979 1
a979 1
	  if (ipass == 1) {
d981 1
a981 1
	        (*nwcs == 0 && ctrl == 0)) {
d986 1
a986 1
	    if (2 < abs(ctrl%10)) {
a995 1
	  }
a996 1
	  if (ipass++ < npass) {
a998 1
	    keyrec = header;
d1001 2
a1002 2
	    i = j = 0;
	    m = 0;
a1003 1
	
a1004 5
	    vptr    = 0x0;
	
	    altlin  = 0;
	    npptr   = 0x0;
	    special = 0x0;
d1014 2
a1015 10
	      wcsfprintf(stderr, "%d WCS keyrecord%s rejected.\n",
	        *nreject, (*nreject==1)?" was":"s were");
	    } else if (ctrl == 4) {
	      wcsfprintf(stderr, "\n");
	      wcsfprintf(stderr, "%5d keyrecord%s rejected for syntax or "
	        "other errors,\n", *nreject, (*nreject==1)?" was":"s were");
	      wcsfprintf(stderr, "%5d %s recognised as syntactically valid, "
	        "and\n", nvalid, (nvalid==1)?"was":"were");
	      wcsfprintf(stderr, "%5d other%s were not recognised as WCS "
	        "keyrecords.\n", nother, (nother==1)?"":"s");
d1018 1
a1018 1
	    return wcspih_final(alts, nwcs, wcs);
a1133 4

      } else {
        /* Signal that there is no wcsprm for this alt. */
        alts[ialt] = -1;
a1146 36
* Interpret EPOCHa keywords.
*---------------------------------------------------------------------------*/

int wcspih_epoch(double *equinox, double epoch)

{
  /* If EQUINOXa is currently undefined then set it from EPOCHa. */
  if (undefined(*equinox)) {
    *equinox = epoch;
  }

  return 0;
}


/*----------------------------------------------------------------------------
* Interpret VSOURCEa keywords.
*---------------------------------------------------------------------------*/

int wcspih_vsource(double *zsource, double vsource)

{
  double beta, c = 299792458.0;

  /* If ZSOURCEa is currently undefined then set it from VSOURCEa. */
  if (undefined(*zsource)) {
    /* Convert relativistic Doppler velocity to redshift. */
    beta = vsource/c;
    *zsource = (1.0 + beta)/sqrt(1.0 - beta*beta) - 1.0;
  }

  return 0;
}


/*----------------------------------------------------------------------------
d1152 2
d1159 1
d1162 13
@


4.25.1.4
log
@Americanized spelling (for consistency).
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.25.1.3 2015/03/15 08:59:20 mcalabre Exp mcalabre $
d682 1
a682 1
	    errmsg = "indices in parameterized keywords must not have "
d751 1
a751 1
	    errmsg = "indices in parameterized keywords must not have "
d908 1
a908 1
	    errmsg = "indices in parameterized keywords must not have "
d1029 1
d1217 1
a1217 1
	      wcsfprintf(stderr, "%.80s\n  Not a recognized WCS keyword.\n",
d1319 1
a1319 1
	      wcsfprintf(stderr, "%5d %s recognized as syntactically valid, "
d1321 1
a1321 1
	      wcsfprintf(stderr, "%5d other%s were not recognized as WCS "
@


4.24
log
@WCSLIB 4.24
@
text
@d3 1
a3 1
  WCSLIB 4.24 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.23.1.1 2014/05/13 05:53:49 mcalabre Exp mcalabre $
@


4.24.1.1
log
@WCSLIB 4.24 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.24 2014/09/18 15:25:00 mcalabre Exp $
@


4.23
log
@WCSLIB 4.23
@
text
@d3 1
a3 1
  WCSLIB 4.23 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.22.1.1 2014/04/12 15:06:32 mcalabre Exp mcalabre $
@


4.23.1.1
log
@WCSLIB 4.23 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.23 2014/05/13 05:50:51 mcalabre Exp $
@


4.22
log
@WCSLIB 4.22
@
text
@d3 1
a3 1
  WCSLIB 4.22 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.21.1.1 2014/03/24 05:15:28 mcalabre Exp mcalabre $
@


4.22.1.1
log
@WCSLIB 4.22 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.22 2014/04/12 15:03:52 mcalabre Exp $
@


4.21
log
@WCSLIB 4.21
@
text
@d3 1
a3 1
  WCSLIB 4.21 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.20.1.2 2014/03/21 06:32:19 mcalabre Exp mcalabre $
@


4.21.1.1
log
@WCSLIB 4.21 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.21 2014/03/24 05:12:27 mcalabre Exp $
@


4.20
log
@WCSLIB 4.20
@
text
@d3 2
a4 2
  WCSLIB 4.20 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2013, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 4.19.1.1 2013/09/29 14:20:38 mcalabre Exp mcalabre $
@


4.20.1.1
log
@WCSLIB 4.20 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.20 2013/12/18 05:42:49 mcalabre Exp $
@


4.20.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2014, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 4.20.1.1 2013/12/18 05:46:55 mcalabre Exp mcalabre $
@


4.19
log
@WCSLIB 4.19
@
text
@d3 1
a3 1
  WCSLIB 4.19 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.18.1.1 2013/07/13 10:02:37 mcalabre Exp mcalabre $
@


4.19.1.1
log
@WCSLIB 4.19 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.19 2013/09/29 14:17:51 mcalabre Exp $
@


4.18
log
@WCSLIB 4.18
@
text
@d3 1
a3 1
  WCSLIB 4.18 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.17.1.1 2013/01/29 05:32:32 cal103 Exp cal103 $
@


4.18.1.1
log
@WCSLIB 4.18 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.18 2013/07/13 10:00:04 mcalabre Exp $
@


4.17
log
@WCSLIB 4.17
@
text
@d3 1
a3 1
  WCSLIB 4.17 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.16.1.2 2013/01/29 03:42:59 cal103 Exp cal103 $
@


4.17.1.1
log
@WCSLIB 4.17 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.17 2013/01/29 05:29:20 cal103 Exp $
@


4.16
log
@WCSLIB 4.16
@
text
@d3 2
a4 2
  WCSLIB 4.16 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2012, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 4.15.1.2 2012/11/07 04:29:45 cal103 Exp cal103 $
d108 1
d938 1
a938 1
	      fprintf(stderr, "%.80s\n  Discarded.\n", wcspih_hdr-80);
d953 1
a953 1
	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcspih_hdr-80, *nreject,
d989 1
a989 1
	          fprintf(stderr, "Found one coordinate representation.\n");
d992 1
a992 1
	        fprintf(stderr, "Found %d coordinate representations.\n",
d1014 1
a1014 1
	      fprintf(stderr, "%d WCS keyrecords were rejected.\n",
@


4.16.1.1
log
@WCSLIB 4.16 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.16 2012/11/07 04:42:44 cal103 Exp $
@


4.16.1.2
log
@Use wcsfprintf() for diagnostic output.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2013, Mark Calabretta
d25 1
a25 1
  $Id: wcspih.l,v 4.16.1.1 2012/11/07 04:45:56 cal103 Exp cal103 $
a107 1
#include "wcsprintf.h"
d937 1
a937 1
	      wcsfprintf(stderr, "%.80s\n  Discarded.\n", wcspih_hdr-80);
d952 1
a952 1
	      wcsfprintf(stderr, "%.80s\n%4d: %s.\n", wcspih_hdr-80, *nreject,
d988 1
a988 1
	          wcsfprintf(stderr, "Found one coordinate representation.\n");
d991 1
a991 1
	        wcsfprintf(stderr, "Found %d coordinate representations.\n",
d1013 1
a1013 1
	      wcsfprintf(stderr, "%d WCS keyrecords were rejected.\n",
@


4.15
log
@WCSLIB 4.15
@
text
@d3 1
a3 1
  WCSLIB 4.15 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.14.1.1 2012/07/13 10:04:44 cal103 Exp cal103 $
d987 3
a989 1
	        fprintf(stderr, "Found one coordinate representation.\n");
d1080 1
a1080 1
  int ialt, npsmax, npvmax, status = 0;
d1089 1
a1089 1
  if (!(*nwcs) && naxis) {
d1124 5
@


4.15.1.1
log
@WCSLIB 4.15 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.15 2012/09/26 14:26:05 cal103 Exp $
@


4.15.1.2
log
@When wcspih() constructs a default coordinate representation it will give
it the special name "DEFAULTS", and will not report "Found one coordinate
representation" (if reporting is enabled).  Change requested by Jasem Mutlaq
for KStars.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.15.1.1 2012/09/26 14:27:51 cal103 Exp cal103 $
d987 1
a987 3
	        if (strcmp(wcs[0]->wcsname, "DEFAULTS") != 0) {
	          fprintf(stderr, "Found one coordinate representation.\n");
	        }
d1078 1
a1078 1
  int ialt, defaults, npsmax, npvmax, status = 0;
d1087 1
a1087 1
  if ((defaults = !(*nwcs) && naxis)) {
a1121 5
        /* Record in wcsname whether this is a default description. */
        if (defaults) {
          strcpy(wcsp->wcsname, "DEFAULTS");
        }

@


4.14
log
@WCSLIB 4.14
@
text
@d3 1
a3 1
  WCSLIB 4.14 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: wcspih.l,v 4.13.1.3 2012/07/13 03:34:20 cal103 Exp cal103 $
@


4.14.1.1
log
@WCSLIB 4.14 development branch.
@
text
@d25 1
a25 1
  $Id: wcspih.l,v 4.14 2012/07/13 10:02:27 cal103 Exp $
@


4.13
log
@WCSLIB 4.13
@
text
@d3 1
a3 1
  WCSLIB 4.13 - an implementation of the FITS WCS standard.
d19 1
a19 1
  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
d21 5
a25 11
  Correspondence concerning WCSLIB may be directed to:
    Internet email: mcalabre@@atnf.csiro.au
    Postal address: Dr. Mark Calabretta
                    Australia Telescope National Facility, CSIRO
                    PO Box 76
                    Epping NSW 1710
                    AUSTRALIA

  Author: Mark Calabretta, Australia Telescope National Facility
  http://www.atnf.csiro.au/~mcalabre/index.html
  $Id: wcspih.l,v 4.12.1.1 2012/02/29 07:59:10 cal103 Exp cal103 $
d108 1
d825 1
a825 1
	        sscanf(yytext, "%lf", (double *)wptr);
@


4.13.1.1
log
@WCSLIB 4.13 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.13 2012/03/14 07:39:30 cal103 Exp $
@


4.13.1.2
log
@Handle locales such as fr_FR where a comma is used to delimit the decimal
part of a floating point number.  Patch provided by Michael Droettboom.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.13.1.1 2012/03/14 07:40:37 cal103 Exp cal103 $
a113 1
#include "wcsutil.h"
d830 1
a830 1
	        wcsutil_str2double(yytext, "%lf", (double *)wptr);
@


4.13.1.3
log
@Changed contact details.
@
text
@d19 1
a19 1
  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
d21 11
a31 5
  Direct correspondence concerning WCSLIB to mark@@calabretta.id.au

  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
  http://www.atnf.csiro.au/people/Mark.Calabretta
  $Id: wcspih.l,v 4.13.1.2 2012/07/12 15:17:21 cal103 Exp cal103 $
@


4.12
log
@WCSLIB 4.12
@
text
@d3 1
a3 1
  WCSLIB 4.12 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: wcspih.l,v 4.11.1.1 2012/02/20 23:31:13 cal103 Exp cal103 $
@


4.12.1.1
log
@WCSLIB 4.12 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.12 2012/02/29 07:57:56 cal103 Exp $
@


4.11
log
@WCSLIB 4.11
@
text
@d3 1
a3 1
  WCSLIB 4.11 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: wcspih.l,v 4.10.1.1 2012/02/05 23:42:46 cal103 Exp cal103 $
@


4.11.1.1
log
@WCSLIB 4.11 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.11 2012/02/20 23:30:02 cal103 Exp $
@


4.10
log
@WCSLIB 4.10
@
text
@d3 1
a3 1
  WCSLIB 4.10 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: wcspih.l,v 4.9.1.1 2012/01/24 05:41:45 cal103 Exp cal103 $
@


4.10.1.1
log
@WCSLIB 4.10 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.10 2012/02/05 23:41:44 cal103 Exp $
@


4.9
log
@WCSLIB 4.9
@
text
@d3 1
a3 1
  WCSLIB 4.9 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: wcspih.l,v 4.8.1.2 2012/01/24 05:23:06 cal103 Exp cal103 $
@


4.9.1.1
log
@WCSLIB 4.9 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.9 2012/01/24 05:40:29 cal103 Exp $
@


4.8
log
@WCSLIB 4.8
@
text
@d3 2
a4 2
  WCSLIB 4.8 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2011, Mark Calabretta
d31 1
a31 1
  $Id: wcspih.l,v 4.7.1.1 2011/02/07 07:04:22 cal103 Exp cal103 $
@


4.8.1.1
log
@WCSLIB 4.8 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.8 2011/08/15 08:05:53 cal103 Exp $
@


4.8.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2012, Mark Calabretta
d31 1
a31 1
  $Id: wcspih.l,v 4.8.1.1 2011/08/15 08:07:06 cal103 Exp cal103 $
@


4.7
log
@WCSLIB 4.7
@
text
@d3 1
a3 1
  WCSLIB 4.7 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: wcspih.l,v 4.6.1.3 2011/01/14 06:33:16 cal103 Exp cal103 $
@


4.7.1.1
log
@WCSLIB 4.7 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.7 2011/02/07 07:03:42 cal103 Exp $
@


4.6
log
@WCSLIB 4.6
@
text
@d3 2
a4 2
  WCSLIB 4.6 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2010, Mark Calabretta
d31 1
a31 1
  $Id: wcspih.l,v 4.5.1.1 2010/07/16 07:05:31 cal103 Exp cal103 $
d157 1
a157 1
	int  altlin, alts[27], iax, idx, ipx, ix, jx, naxis, *npptr,
d165 6
a170 6
	for (iax = 0; iax < 27; iax++) {
	  alts[iax] = 0;
	  npv[iax] = 0;
	  nps[iax] = 0;
	  epoch[iax]   = UNDEFINED;
	  vsource[iax] = UNDEFINED;
d759 1
a759 1
	      for (iax = 0; iax < *nwcs; iax++) {
d763 1
a763 1
	          iax = alts[a-'A'+1];
d767 2
a768 2
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
d805 1
a805 1
	      for (iax = 0; iax < *nwcs; iax++) {
d809 1
a809 1
	          iax = alts[a-'A'+1];
d813 2
a814 2
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
d823 4
a826 4
	          ipx = (*wcs+iax)->npv++;
	          (*wcs+iax)->pv[ipx].i = i;
	          (*wcs+iax)->pv[ipx].m = m;
	          wptr = &((*wcs+iax)->pv[ipx].value);
d834 1
a834 1
	          (*wcs+iax)->altlin |= altlin;
d863 1
a863 1
	      for (iax = 0; iax < *nwcs; iax++) {
d867 1
a867 1
	          iax = alts[a-'A'+1];
d871 2
a872 2
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
d881 4
a884 4
	          ipx = (*wcs+iax)->nps++;
	          (*wcs+iax)->ps[ipx].i = i;
	          (*wcs+iax)->ps[ipx].m = m;
	          wptr = (*wcs+iax)->ps[ipx].value;
d1037 1
a1037 1
  int iax, *ip;
d1043 1
a1043 1
  iax = 0;
d1045 1
a1045 1
    iax = a - 'A' + 1;
d1048 1
a1048 1
  ip = alts + iax;
d1064 1
a1064 1
    npptr[iax]++;
d1083 1
a1083 1
  int iax, npsmax, npvmax, status = 0;
d1088 2
a1089 2
  for (iax = 0; iax < 27; iax++) {
    if (alts[iax]) (*nwcs)++;
d1112 2
a1113 2
    for (iax = 0; iax < 27; iax++) {
      if (alts[iax]) {
d1115 3
a1117 3
        wcsnpv(npv[iax]);
        wcsnps(nps[iax]);
        if ((status = wcsini(1, alts[iax], wcsp))) {
d1123 2
a1124 2
        if (iax) {
          wcsp->alt[0] = 'A' + iax - 1;
d1128 1
a1128 1
        alts[iax] = (*nwcs)++;
d1155 1
a1155 1
  int iax, status;
d1158 1
a1158 1
  for (iax = 0; iax < *nwcs; iax++) {
d1160 1
a1160 1
    if (undefined((*wcs+iax)->equinox) && !undefined(epoch[iax])) {
d1162 1
a1162 1
      (*wcs+iax)->equinox = epoch[iax];
d1166 1
a1166 1
    if (undefined((*wcs+iax)->zsource) && !undefined(vsource[iax])) {
d1168 2
a1169 2
      beta = vsource[iax]/c;
      (*wcs+iax)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
d1173 1
a1173 1
    if ((status = wcstab(*wcs+iax))) {
@


4.6.1.1
log
@WCSLIB 4.6 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.6 2010/11/16 06:15:31 cal103 Exp $
@


4.6.1.2
log
@Renamed iax -> ialt (no functional changes).
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.6.1.1 2010/11/16 06:16:19 cal103 Exp cal103 $
d157 1
a157 1
	int  altlin, alts[27], ialt, idx, ipx, ix, jx, naxis, *npptr,
d165 6
a170 6
	for (ialt = 0; ialt < 27; ialt++) {
	  alts[ialt] = 0;
	  npv[ialt] = 0;
	  nps[ialt] = 0;
	  epoch[ialt]   = UNDEFINED;
	  vsource[ialt] = UNDEFINED;
d759 1
a759 1
	      for (ialt = 0; ialt < *nwcs; ialt++) {
d763 1
a763 1
	          ialt = alts[a-'A'+1];
d767 2
a768 2
	        if (ialt) {
	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
d805 1
a805 1
	      for (ialt = 0; ialt < *nwcs; ialt++) {
d809 1
a809 1
	          ialt = alts[a-'A'+1];
d813 2
a814 2
	        if (ialt) {
	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
d823 4
a826 4
	          ipx = (*wcs+ialt)->npv++;
	          (*wcs+ialt)->pv[ipx].i = i;
	          (*wcs+ialt)->pv[ipx].m = m;
	          wptr = &((*wcs+ialt)->pv[ipx].value);
d834 1
a834 1
	          (*wcs+ialt)->altlin |= altlin;
d863 1
a863 1
	      for (ialt = 0; ialt < *nwcs; ialt++) {
d867 1
a867 1
	          ialt = alts[a-'A'+1];
d871 2
a872 2
	        if (ialt) {
	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
d881 4
a884 4
	          ipx = (*wcs+ialt)->nps++;
	          (*wcs+ialt)->ps[ipx].i = i;
	          (*wcs+ialt)->ps[ipx].m = m;
	          wptr = (*wcs+ialt)->ps[ipx].value;
d1037 1
a1037 1
  int ialt, *ip;
d1043 1
a1043 1
  ialt = 0;
d1045 1
a1045 1
    ialt = a - 'A' + 1;
d1048 1
a1048 1
  ip = alts + ialt;
d1064 1
a1064 1
    npptr[ialt]++;
d1083 1
a1083 1
  int ialt, npsmax, npvmax, status = 0;
d1088 2
a1089 2
  for (ialt = 0; ialt < 27; ialt++) {
    if (alts[ialt]) (*nwcs)++;
d1112 2
a1113 2
    for (ialt = 0; ialt < 27; ialt++) {
      if (alts[ialt]) {
d1115 3
a1117 3
        wcsnpv(npv[ialt]);
        wcsnps(nps[ialt]);
        if ((status = wcsini(1, alts[ialt], wcsp))) {
d1123 2
a1124 2
        if (ialt) {
          wcsp->alt[0] = 'A' + ialt - 1;
d1128 1
a1128 1
        alts[ialt] = (*nwcs)++;
d1155 1
a1155 1
  int ialt, status;
d1158 1
a1158 1
  for (ialt = 0; ialt < *nwcs; ialt++) {
d1160 1
a1160 1
    if (undefined((*wcs+ialt)->equinox) && !undefined(epoch[ialt])) {
d1162 1
a1162 1
      (*wcs+ialt)->equinox = epoch[ialt];
d1166 1
a1166 1
    if (undefined((*wcs+ialt)->zsource) && !undefined(vsource[ialt])) {
d1168 2
a1169 2
      beta = vsource[ialt]/c;
      (*wcs+ialt)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
d1173 1
a1173 1
    if ((status = wcstab(*wcs+ialt))) {
@


4.6.1.3
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2011, Mark Calabretta
d31 1
a31 1
  $Id: wcspih.l,v 4.6.1.2 2010/11/24 01:22:53 cal103 Exp cal103 $
@


4.5
log
@WCSLIB 4.5
@
text
@d3 1
a3 1
  WCSLIB 4.5 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: wcspih.l,v 4.4.1.3 2010/07/07 13:39:54 cal103 Exp cal103 $
@


4.5.1.1
log
@WCSLIB 4.5 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.5 2010/07/16 07:01:25 cal103 Exp $
@


4.4
log
@WCSLIB 4.4
@
text
@d3 2
a4 2
  WCSLIB 4.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2009, Mark Calabretta
d31 1
a31 1
  $Id: wcspih.l,v 4.3.1.4 2009/07/23 04:52:23 cal103 Exp cal103 $
d139 2
a140 2
int wcspih_final(int alts[], double epoch[], int velref[], double vsource[],
        int *nwcs, struct wcsprm **wcs);
d158 1
a158 1
	     nps[27], npv[27], pass, status, valtype, velref[27], voff;
a169 1
	  velref[iax]  = 0;
d489 1
a489 6
	    if (pass == 2) {
	      vptr = velref;
	      if (a >= 'A') {
	        vptr = (void *)((int *)vptr + alts[a-'A'+1]);
	      }
	    }
d491 1
a491 1
	    unput(' ');
d1020 1
a1020 1
	    return wcspih_final(alts, epoch, velref, vsource, nwcs, wcs);
d1144 1
a1144 2
* Interpret any VELREF keywords encountered for each coordinate
* representation.
a1149 1
  int velref[],
d1155 1
a1155 3
  const char *specsys[] = {"LSRK", "BARYCENT", "TOPOCENT",
                           "LSRD", "GEOCENTR", "SOURCE", "GALACTOC"};
  int iax, ivf, status;
a1164 11
    /* Check for VELREF overriding SPECSYSa. */
    if (velref[iax]) {
      /* Set SPECSYSa. */
      if ((*wcs+iax)->specsys[0] == '\0') {
        ivf = velref[iax]%256 - 1;
        if (0 <= ivf && ivf < 7) {
          sprintf((*wcs+iax)->specsys, "%s", specsys[ivf]);
        }
      }
    }

@


4.4.1.1
log
@WCSLIB 4.4 development branch.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.4 2009/08/06 07:41:33 cal103 Exp $
@


4.4.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2010, Mark Calabretta
d31 1
a31 1
  $Id: wcspih.l,v 4.4.1.1 2009/08/10 08:52:49 cal103 Exp cal103 $
@


4.4.1.3
log
@Interpretation of the VELREF keyword is now done elsewhere.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.4.1.2 2010/01/19 03:42:50 cal103 Exp cal103 $
d139 2
a140 2
int wcspih_final(int alts[], double epoch[], double vsource[], int *nwcs,
        struct wcsprm **wcs);
d158 1
a158 1
	     nps[27], npv[27], pass, status, valtype, voff;
d170 1
d490 6
a495 1
	    if (pass == 2) vptr = &((*wcs)->velref);
d497 1
a497 1
	    unput(a);
d1026 1
a1026 1
	    return wcspih_final(alts, epoch, vsource, nwcs, wcs);
d1150 2
a1151 1
* Interpret special keywords encountered for each coordinate representation.
d1157 1
d1163 3
a1165 1
  int iax, status;
d1175 11
@


4.3
log
@WCSLIB 4.3
@
text
@d3 2
a4 2
    WCSLIB 4.3 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2007, Mark Calabretta
d6 1
a6 1
    This file is part of WCSLIB.
d8 24
a31 24
    WCSLIB is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the
    Free Software Foundation, either version 3 of the License, or (at your
    option) any later version.

    WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
    more details.

    You should have received a copy of the GNU Lesser General Public License
    along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

    Correspondence concerning WCSLIB may be directed to:
       Internet email: mcalabre@@atnf.csiro.au
       Postal address: Dr. Mark Calabretta
                       Australia Telescope National Facility, CSIRO
                       PO Box 76
                       Epping NSW 1710
                       AUSTRALIA

    Author: Mark Calabretta, Australia Telescope National Facility
    http://www.atnf.csiro.au/~mcalabre/index.html
    $Id: wcspih.l,v 4.2.1.19 2007/12/27 05:06:52 cal103 Exp cal103 $
d34 3
a36 3
*   wcspih.l is a Flex description file containing the definition of a lexical
*   scanner for parsing the WCS keyrecords from a FITS primary image or image
*   extension header.
d38 2
a39 2
*   wcspih.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a
*   description of the user interface and operating notes.
d41 9
a49 9
*   Implementation notes
*   --------------------
*   Use of the WCSAXESa keyword is not mandatory.  Its default value is "the
*   larger of NAXIS and the largest index of these keywords [i.e. CRPIXj,
*   PCi_j or CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS
*   header".  Consequently the definition of WCSAXESa effectively invalidates
*   the use of NAXIS for determining the number of coordinate axes and forces
*   a preliminary pass through the header to determine the "largest index" in
*   headers where WCSAXESa was omitted.
d51 5
a55 5
*   Furthermore, since the use of WCSAXESa is optional, there is no way to
*   determine the number of coordinate representations (the "a" value) other
*   than by parsing all of the WCS keywords in the header; even if WCSAXESa
*   was specified for some representations it cannot be known in advance
*   whether it was specified for all of those present in the header.
d57 7
a63 7
*   Hence the definition of WCSAXESa forces the scanner must be implemented in
*   two passes.  The first pass is used to determine the number of coordinate
*   representations (up to 27) and the number of coordinate axes in each.
*   Effectively WCSAXESa is ignored unless it exceeds the "largest index" in
*   which case the keywords for the extra axes assume their default values.
*   The number of PVi_ma and PSi_ma keywords in each representation is also
*   counted in the first pass.
d65 3
a67 3
*   On completion of the first pass, memory is allocated for an array of the
*   required number of wcsprm structs and each of these is initialized
*   appropriately.  These structs are filled in the second pass.
d69 2
a70 2
*   The parser does not check for duplicated keywords, it accepts the last
*   encountered.
d106 1
d139 4
d144 4
a147 4
int  wcspih_inits(int alts[], int npv[], int nps[], int *nwcs,
                  struct wcsprm **wcs);
int  wcspih_final(int alts[], double epoch[], int velref[], double vsource[],
                  int *nwcs, struct wcsprm **wcs);
d162 1
a162 1
        int yylex_destroy(void);
d201 6
d512 1
a512 1
	  if (relax & WCSHDR_VSOURCEa) {
d599 1
a599 1
	  /* Invalid axis number will be caught by <VALUE>. */
d689 1
a689 1
	  /* Invalid parameter will be caught by <VALUE>. */
d987 1
a987 1
<<EOF>> {
d990 1
a990 1
	    if ((status = wcspih_inits(alts, npv, nps, nwcs, wcs)) ||
d1018 1
a1018 1

d1033 3
a1035 3
*   Determine the number of coordinate representations (up to 27) and the
*   number of coordinate axes in each, and count the number of PVi_ma and
*   PSi_ma keywords in each representation.
d1076 2
a1077 2
*   Allocate memory for an array of the required number of wcsprm structs and
*   initialize each of them.
d1081 1
d1098 7
d1150 2
a1151 2
*   Interpret any VELREF keywords encountered for each coordinate
*   representation.
@


4.3.1.1
log
@WCSLIB 4.3 development branch.
@
text
@d3 2
a4 2
    WCSLIB 4.4 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2008, Mark Calabretta
d31 1
a31 1
    $Id: wcspih.l,v 4.3 2007/12/27 05:41:36 cal103 Exp cal103 $
@


4.3.1.2
log
@Use a preprocessor macro to override the call to exit() in
yy_fatal_error() with a call to longjmp(), thereby allowing wcspih()
to handle parser errors; if NAXIS is non-zero but there were no WCS
keywords with an alternate version code then create a default WCS
with blank alternate version.
@
text
@d4 1
a4 1
    Copyright (C) 1995-2009, Mark Calabretta
d31 1
a31 1
    $Id: wcspih.l,v 4.3.1.2 2008/04/02 03:51:53 cal103 Exp cal103 $
d57 1
a57 1
*   Hence the definition of WCSAXESa forces the scanner to be implemented in
a105 1
#include <setjmp.h>
a137 4
int wcspih_final(int alts[], double epoch[], int velref[], double vsource[],
        int *nwcs, struct wcsprm **wcs);
int wcspih_inits(int naxis, int alts[], int npv[], int nps[], int *nwcs,
        struct wcsprm **wcs);
d139 4
a142 4

/* Used in preempting the call to exit() by yy_fatal_error(). */
jmp_buf wcspih_abort_jmp_env;
#define exit(status) longjmp(wcspih_abort_jmp_env, status)
d157 1
a157 1
	int yylex_destroy(void);
a195 6
	
	/* Return here via longjmp() invoked by yy_fatal_error(). */
	if (setjmp(wcspih_abort_jmp_env)) {
	  return 3;
	}
	
d588 1
a588 1
	  /* Invalid axis numbers will be caught by <VALUE>. */
d678 1
a678 1
	  /* Invalid parameters will be caught by <VALUE>. */
d979 1
a979 1
	    if ((status = wcspih_inits(naxis, alts, npv, nps, nwcs, wcs)) ||
d1007 1
a1007 1
	
a1069 1
  int naxis,
a1085 7
  if (!(*nwcs) && naxis) {
    /* NAXIS is non-zero but there were no WCS keywords with an alternate
       version code; create a default WCS with blank alternate version. */
    wcspih_naxes(naxis, 0, 0, ' ', alts, 0x0);
    *nwcs = 1;
  }

@


4.3.1.3
log
@Changed indentation in the prologue.
@
text
@d3 2
a4 2
  WCSLIB 4.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2009, Mark Calabretta
d6 1
a6 1
  This file is part of WCSLIB.
d8 24
a31 24
  WCSLIB is free software: you can redistribute it and/or modify it under the
  terms of the GNU Lesser General Public License as published by the Free
  Software Foundation, either version 3 of the License, or (at your option)
  any later version.

  WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
  more details.

  You should have received a copy of the GNU Lesser General Public License
  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

  Correspondence concerning WCSLIB may be directed to:
    Internet email: mcalabre@@atnf.csiro.au
    Postal address: Dr. Mark Calabretta
                    Australia Telescope National Facility, CSIRO
                    PO Box 76
                    Epping NSW 1710
                    AUSTRALIA

  Author: Mark Calabretta, Australia Telescope National Facility
  http://www.atnf.csiro.au/~mcalabre/index.html
  $Id: wcspih.l,v 4.3.1.2 2009/04/30 02:33:27 cal103 Exp cal103 $
d34 3
a36 3
* wcspih.l is a Flex description file containing the definition of a lexical
* scanner for parsing the WCS keyrecords from a FITS primary image or image
* extension header.
d38 2
a39 2
* wcspih.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
* of the user interface and operating notes.
d41 9
a49 9
* Implementation notes
* --------------------
* Use of the WCSAXESa keyword is not mandatory.  Its default value is "the
* larger of NAXIS and the largest index of these keywords [i.e. CRPIXj, PCi_j
* or CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS header".
* Consequently the definition of WCSAXESa effectively invalidates the use of
* NAXIS for determining the number of coordinate axes and forces a preliminary
* pass through the header to determine the "largest index" in headers where
* WCSAXESa was omitted.
d51 5
a55 5
* Furthermore, since the use of WCSAXESa is optional, there is no way to
* determine the number of coordinate representations (the "a" value) other
* than by parsing all of the WCS keywords in the header; even if WCSAXESa was
* specified for some representations it cannot be known in advance whether it
* was specified for all of those present in the header.
d57 7
a63 7
* Hence the definition of WCSAXESa forces the scanner to be implemented in two
* passes.  The first pass is used to determine the number of coordinate
* representations (up to 27) and the number of coordinate axes in each.
* Effectively WCSAXESa is ignored unless it exceeds the "largest index" in
* which case the keywords for the extra axes assume their default values.  The
* number of PVi_ma and PSi_ma keywords in each representation is also counted
* in the first pass.
d65 3
a67 3
* On completion of the first pass, memory is allocated for an array of the
* required number of wcsprm structs and each of these is initialized
* appropriately.  These structs are filled in the second pass.
d69 2
a70 2
* The parser does not check for duplicated keywords, it accepts the last
* encountered.
d987 1
a987 1
<<EOF>>	 {
d1033 3
a1035 3
* Determine the number of coordinate representations (up to 27) and the
* number of coordinate axes in each, and count the number of PVi_ma and
* PSi_ma keywords in each representation.
d1076 2
a1077 2
* Allocate memory for an array of the required number of wcsprm structs and
* initialize each of them.
d1150 2
a1151 2
* Interpret any VELREF keywords encountered for each coordinate
* representation.
@


4.3.1.4
log
@Renamed WCSHDR_VSOURCEa -> WCSHDR_VSOURCE.
@
text
@d31 1
a31 1
  $Id: wcspih.l,v 4.3.1.3 2009/07/22 04:52:32 cal103 Exp cal103 $
d512 1
a512 1
	  if (relax & WCSHDR_VSOURCE) {
@


4.2
log
@WCSLIB 4.2: no need to cast the return value of calloc().
@
text
@d2 31
d34 3
a36 28
*   WCSLIB 4.2 - an implementation of the FITS WCS standard.
*   Copyright (C) 1995-2005, Mark Calabretta
*
*   WCSLIB 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.
*
*   WCSLIB 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 WCSLIB; if not, write to the Free Software Foundation, Inc.,
*   59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
*
*   Correspondence concerning WCSLIB may be directed to:
*      Internet email: mcalabre@@atnf.csiro.au
*      Postal address: Dr. Mark Calabretta
*                      Australia Telescope National Facility, CSIRO
*                      PO Box 76
*                      Epping NSW 1710
*                      AUSTRALIA
*
*   Author: Mark Calabretta, Australia Telescope National Facility
*   $Id: wcspih.l,v 4.1 2005/08/25 12:39:53 cal103 Exp cal103 $
*=============================================================================
d38 2
a39 2
*   wcspih.l is a Flex description file containing a lexical scanner
*   definition for extracting the WCS cards from a FITS header.
d41 9
a49 1
*   It requires Flex v2.5.4 or later.
d51 5
a55 2
*   Refer to wcshdr.h for a description of the user interface and operating
*   notes.
d57 7
a63 5
*   The flawed definition of WCSAXESa and its nullifying effect on NAXIS
*   forces the scanner to be implemented in two passes.  A first pass is
*   required to determine the number of coordinate representations (up to 27)
*   and the number of coordinate axes in each; it also counts the number of
*   PVi_ma and PSi_ma cards in each representation.
d67 4
a70 2
*   appropriately.  These structs are filled in the second pass.  The parser
*   does not check for duplicated cards, it accepts the last encountered.
d78 2
d118 1
a118 1
#define YY_DECL int wcspih(char *header, int ncards, int relax, int ctrl, \
d123 1
a123 1
	  if (wcspih_ncards) { \
d127 1
a127 1
	    wcspih_ncards--; \
a133 5
#ifdef DEBUG
  /* Print text as it is matched. */
  #define YY_USER_ACTION printf("Rule %03d: \"%s\"\n", yy_act, yytext);
#endif

d136 1
a136 1
int  wcspih_ncards;
d138 1
a138 1
void wcspih_naxes(int naxis, int i, int j, char alt, int alts[], int *npptr);
d147 7
a153 4

	char alt, *cptr, errmsg[80], *hptr;
	int  a, altlin, alts[27], i, j, k, m, naxis, ndx, *npptr, nps[27],
	     npv[27], pass, status, type, velref[27], voff;
d157 1
d160 7
a166 7
	for (a = 0; a < 27; a++) {
	  alts[a] = 0;
	  npv[a] = 0;
	  nps[a] = 0;
	  epoch[a]   = UNDEFINED;
	  velref[a]  = 0;
	  vsource[a] = UNDEFINED;
d169 1
d171 1
a171 1
	wcspih_ncards = ncards;
d173 1
d175 1
d177 15
a195 8
	i = j = m = 0;
	alt = ' ';
	ndx  = -1;
	type = -1;
	altlin = 0;
	npptr = 0x0;
	vptr  = 0x0;
	
d199 1
a199 2
^NAXIS"   "="  "*{INTEGER} {
	  /* Rule 001. */
d205 1
a209 1
	    yyless(0);
d214 1
a214 2
^WCSAXES{ALT}="  "*{INTEGER} {
	  /* Rule 002. */
d216 2
a217 2
	    sscanf(yytext, "WCSAXES%c= %d", &alt, &i);
	    wcspih_naxes(naxis, i, 0, alt, alts, 0);
a221 7
^WCSNAME {
	  /* Rule 003. */
	  if (*wcs) vptr = (*wcs)->wcsname;
	  type = STRING;
	  BEGIN(CCCCCCCa);
	}

d223 2
a224 3
	  /* Rule 004. */
	  if (*wcs) vptr = &((*wcs)->crpix);
	  type = FLOAT;
d229 3
a231 6
	  /* Rule 005. */
	  if (*wcs) {
	    vptr = &((*wcs)->pc);
	    altlin = 1;
	  }
	  type = FLOAT;
d236 3
a238 6
	  /* Rule 006. */
	  if (*wcs) {
	    vptr = &((*wcs)->cd);
	    altlin = 2;
	  }
	  type = FLOAT;
d243 2
a244 3
	  /* Rule 007. */
	  if (*wcs) vptr = &((*wcs)->cdelt);
	  type = FLOAT;
d249 3
a251 6
	  /* Rule 008. */
	  if (*wcs) {
	    vptr = &((*wcs)->crota);
	    altlin = 4;
	  }
	  type = FLOAT;
d256 2
a257 3
	  /* Rule 009. */
	  if (*wcs) vptr = &((*wcs)->cunit);
	  type = STRING;
d262 2
a263 3
	  /* Rule 010. */
	  if (*wcs) vptr = &((*wcs)->ctype);
	  type = STRING;
d268 2
a269 3
	  /* Rule 011. */
	  if (*wcs) vptr = &((*wcs)->crval);
	  type = FLOAT;
d273 16
a288 5
^CNAME	{
	  /* Rule 012. */
	  if (*wcs) vptr = &((*wcs)->cname);
	  type = STRING;
	  BEGIN(CCCCCia);
d291 5
a295 5
^CRDER	{
	  /* Rule 013. */
	  if (*wcs) vptr = &((*wcs)->crder);
	  type = FLOAT;
	  BEGIN(CCCCCia);
d298 4
a301 5
^CSYER	{
	  /* Rule 014. */
	  if (*wcs) vptr = &((*wcs)->csyer);
	  type = FLOAT;
	  BEGIN(CCCCCia);
d305 2
a306 1
	  /* Rule 015. */
a307 2
	  if (*wcs) vptr = &((*wcs)->pv);
	  type = FLOAT;
d312 2
a313 1
	  /* Rule 016. */
a314 2
	  if (*wcs) vptr = &((*wcs)->pv);
	  type = FLOAT;
d319 2
a320 1
	  /* Rule 017. */
a321 2
	  if (*wcs) vptr = &((*wcs)->ps);
	  type = STRING;
d325 4
a328 5
^LONPOLE {
	  /* Rule 018. */
	  if (*wcs) vptr = &((*wcs)->lonpole);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
d331 4
a334 5
^LATPOLE {
	  /* Rule 019. */
	  if (*wcs) vptr = &((*wcs)->latpole);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
d337 4
a340 6
^RADECSYS {
	  /* Rule 020. */
	  unput(' ');
	  if (*wcs) vptr = (*wcs)->radesys;
	  type = STRING;
	  BEGIN(CCCCCCCa);
d343 5
a347 5
^RADESYS {
	  /* Rule 021. */
	  if (*wcs) vptr = (*wcs)->radesys;
	  type = STRING;
	  BEGIN(CCCCCCCa);
d350 5
a354 5
^EQUINOX {
	  /* Rule 022. */
	  if (*wcs) vptr = &((*wcs)->equinox);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
d358 1
a358 2
	  /* Rule 023. */
	  sscanf(yytext, "EPOCH%c", &alt);
d360 3
a362 2
	  if (alt == ' ' || relax & (WCSHDR_all | WCSHDR_EPOCHa)) {
	    if (*wcs) {
d364 2
a365 2
	      if (alt >= 'A') {
	        vptr = (void *)((double *)vptr + alts[alt-'A'+1]);
a369 1
	    type = FLOAT;
d373 1
a373 2
	    sprintf(errmsg, "EPOCH keyword may not have an alternate "
	                    "version code");
d381 3
a383 5
^RESTFREQ {
	  /* Rule 024. */
	  unput(' ');
	  if (*wcs) vptr = &((*wcs)->restfrq);
	  type = FLOAT;
d387 38
a424 4
^RESTFRQ {
	  /* Rule 025. */
	  if (*wcs) vptr = &((*wcs)->restfrq);
	  type = FLOAT;
d428 14
a441 5
^RESTWAV {
	  /* Rule 026. */
	  if (*wcs) vptr = &((*wcs)->restwav);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
d445 2
a446 3
	  /* Rule 027. */
	  if (*wcs) vptr = (*wcs)->specsys;
	  type = STRING;
d451 20
a470 3
	  /* Rule 028. */
	  if (*wcs) vptr = (*wcs)->ssysobs;
	  type = STRING;
d475 1
a475 2
	  /* Rule 029. */
	  sscanf(yytext, "VELREF%c", &alt);
d477 3
a479 2
	  if (alt == ' ' || relax & (WCSHDR_all | WCSHDR_VELREFa)) {
	    if (*wcs) {
d481 2
a482 2
	      if (alt >= 'A') {
	        vptr = (void *)((int *)vptr + alts[alt-'A'+1]);
a486 1
	    type = INTEGER;
d490 1
a490 2
	    sprintf(errmsg, "VELREF keyword may not have an alternate "
	                    "version code");
a497 14
^VELOSYS {
	  /* Rule 030. */
	  if (*wcs) vptr = &((*wcs)->velosys);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
	}

^SSYSSRC {
	  /* Rule 031. */
	  if (*wcs) vptr = (*wcs)->ssyssrc;
	  type = STRING;
	  BEGIN(CCCCCCCa);
	}

d499 1
a499 2
	  /* Rule 032. */
	  sscanf(yytext, "VSOURCE%c", &alt);
d501 3
a503 2
	  if (relax & (WCSHDR_all | WCSHDR_VSOURCEa)) {
	    if (*wcs) {
d505 2
a506 2
	      if (alt >= 'A') {
	        vptr = (void *)((double *)vptr + alts[alt-'A'+1]);
a510 1
	    type = FLOAT;
d514 1
a514 1
	    sprintf(errmsg, "Deprecated VSOURCEa keyword rejected");
d522 3
a524 4
^ZSOURCE {
	  /* Rule 033. */
	  if (*wcs) vptr = &((*wcs)->zsource);
	  type = FLOAT;
d528 4
a531 47
^OBSGEO-X {
	  /* Rule 034. */
	  if (*wcs) vptr = (*wcs)->obsgeo;
	  type = FLOAT;
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-Y {
	  /* Rule 035. */
	  if (*wcs) vptr = (*wcs)->obsgeo + 1;
	  type = FLOAT;
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-Z {
	  /* Rule 036. */
	  if (*wcs) vptr = (*wcs)->obsgeo + 2;
	  type = FLOAT;
	  BEGIN(CCCCCCCC);
	}

^DATE-OBS {
	  /* Rule 037. */
	  if (*wcs) vptr = (*wcs)->dateobs;
	  type = STRING;
	  BEGIN(CCCCCCCC);
	}

^DATE-AVG {
	  /* Rule 038. */
	  if (*wcs) vptr = (*wcs)->dateavg;
	  type = STRING;
	  BEGIN(CCCCCCCC);
	}

^MJD-OBS" " {
	  /* Rule 039. */
	  if (*wcs) vptr = &((*wcs)->mjdobs);
	  type = FLOAT;
	  BEGIN(CCCCCCCC);
	}

^MJD-AVG" " {
	  /* Rule 040 */
	  if (*wcs) vptr = &((*wcs)->mjdavg);
	  type = FLOAT;
	  BEGIN(CCCCCCCC);
a534 1
	  /* Rule 041. */
d536 3
a538 2
	  if (wcspih_ncards) {
	    sprintf(errmsg, "Illegal cards following END card");
a545 56
	  /* Rule 042. */
	  yyless(0);
	  BEGIN(DISCARD);
	}

<CROTAi>{I1}{ALT}" " |
<CROTAi>{I2}{ALT} {
	  /* Rules 043-044. */
	  sscanf(yytext, "%d%c", &i, &alt);
	  if (alt == ' ' || relax & (WCSHDR_all | WCSHDR_CROTAia)) {
	    ndx = i - 1;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    sprintf(errmsg, "CROTAn keyword may not have an alternate "
	                    "version code");
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

<CROTAi>{I3} {
	  /* Rule 045. */
	  sscanf(yytext, "%d", &i);
	  alt = ' ';
	  ndx = i - 1;
	  BEGIN(VALUE);
	}

<CROTAi>. {
	  /* Rule 046. */
	  BEGIN(DISCARD);
	}

<PROJPn>{I0}"  " {
	  /* Rule 047. */
	  if (relax & (WCSHDR_all | WCSHDR_PROJPn)) {
	    sscanf(yytext, "%d", &m);
	    i = 0;
	    alt = ' ';
	    ndx = -1;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    sprintf(errmsg, "Defunct PROJPn keyword rejected");
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

<PROJPn>. {
	  /* Rule 048. */
d551 2
a552 3
	  /* Rules 049-050. */
	  sscanf(yytext, "%d%c", &i, &alt);
	  ndx = i - 1;
d557 1
a557 1
	  /* Rule 051. */
a558 2
	  alt = ' ';
	  ndx = i - 1;
a562 1
	  /* Rule 052. */
d569 3
a571 6
<CCi_ja>{I1}_{I3}{ALT} |
<CCi_ja>{I2}_{I2}{ALT} |
<CCi_ja>{I3}_{I1}{ALT} {
	  /* Rules 053-058. */
	  sscanf(yytext, "%d_%d%c", &i, &j, &alt);
	  if (*wcs) {
d573 2
a574 2
	    if (alt != ' ') {
	      wcsp += alts[alt-'A'+1];
d577 1
a577 1
	    ndx = (i-1)*(wcsp->naxis) + j - 1;
d582 2
d588 1
a588 1
	  /* Rules 059-062. */
a589 4
	  alt = ' ';
	  if (*wcs) {
	    ndx = (i-1)*((*wcs)->naxis) + j - 1;
	  }
d594 3
a596 4
	  /* Rule 063: This covers the defunct forms CD00i00j and PC00i00j. */
	  if ((relax & WCSHDR_all) ||
	      (relax & WCSHDR_PC00i00j) && altlin == 1 ||
	      (relax & WCSHDR_CD00i00j) && altlin == 2) {
d598 3
a600 3
	    alt = ' ';
	    if (*wcs) {
	      ndx = (i-1)*((*wcs)->naxis) + j - 1;
d605 1
d616 44
a659 1
	  /* Rule 064. */
d665 4
a668 7
<CCi_ma>{I2}_{I1}{ALT}" " |
<CCi_ma>{I1}_{I3}{ALT} |
<CCi_ma>{I2}_{I2}{ALT} |
<CCi_ma>{I3}_{I1}{ALT} {
	  /* Rules 065-070. */
	  sscanf(yytext, "%d_%d%c", &i, &m, &alt);
	  ndx = -1;
d672 2
d677 2
a678 2
<CCi_ma>{I4}_{I1} {
	  /* Rules 071-074. */
a679 2
	  alt = ' ';
	  ndx = -1;
a683 1
	  /* Rule 075. */
d687 15
a701 5
<CCCCCCCa>{ALT} {
	  /* Rule 076. */
	  ndx = -1;
	  sscanf(yytext, "%c", &alt);
	  BEGIN(VALUE);
d704 1
a704 2
<CCCCCCCa>. {
	  /* Rule 077. */
a707 8
<CCCCCCCC>. {
	  /* Rule 078. */
	  unput(yytext[0]);
	  ndx = -1;
	  alt = 0;
	  BEGIN(VALUE);
	}

d709 16
a724 7
	  /* Rule 079. */
	  if (type == INTEGER) {
	    BEGIN(INTEGER_VAL);
	  } else if (type == FLOAT) {
	    BEGIN(FLOAT_VAL);
	  } else if (type == STRING) {
	    BEGIN(STRING_VAL);
d726 12
a737 2
	    sprintf(errmsg, "Internal parser ERROR, bad data type: %d", type);
	    BEGIN(ERROR);
d742 1
a742 2
	  /* Rule 080. */
	  sprintf(errmsg, "Invalid KEYWORD = VALUE syntax");
a746 1
	  /* Rule 081. */
d748 1
a748 1
	    wcspih_naxes(naxis, i, j, alt, alts, npptr);
d754 1
a754 1
	      for (a = 0; a < *nwcs; a++) {
d756 3
a758 3
		/* to every alternate; these have alt == 0. */
	        if (alt >= 'A') {
	          a = alts[alt-'A'+1];
d762 2
a763 2
	        if (a) {
	          voff = (char *)(*wcs+a) - (char *)(*wcs);
d768 2
a769 2
	        if (ndx >= 0) {
	          wptr = *((int **)wptr) + ndx;
d775 1
a775 1
	        if (alt) break;
d781 1
a781 1
	      sprintf(errmsg, "Internal parser ERROR, null int pointer");
d788 1
a788 2
	  /* Rule 082. */
	  sprintf(errmsg, "An integer value was expected");
a792 1
	  /* Rule 083. */
d794 1
a794 1
	    wcspih_naxes(naxis, i, j, alt, alts, npptr);
d800 1
a800 1
	      for (a = 0; a < *nwcs; a++) {
d802 3
a804 3
		/* apply to every alternate; these have alt == 0.  */
	        if (alt >= 'A') {
	          a = alts[alt-'A'+1];
d808 2
a809 2
	        if (a) {
	          voff = (char *)(*wcs+a) - (char *)(*wcs);
d814 2
a815 2
	        if (ndx >= 0) {
	          wptr = *((double **)wptr) + ndx;
d818 4
a821 4
	          k = (*wcs+a)->npv++;
	          (*wcs+a)->pv[k].i = i;
	          (*wcs+a)->pv[k].m = m;
	          wptr = &((*wcs+a)->pv[k].value);
d829 1
a829 1
	          (*wcs+a)->altlin |= altlin;
d833 1
a833 1
	        if (alt) break;
d839 1
a839 1
	      sprintf(errmsg, "Internal parser ERROR, null float pointer");
d846 1
a846 2
	  /* Rule 084. */
	  sprintf(errmsg, "A floating-point value was expected");
a850 1
	  /* Rule 085. */
d852 1
a852 1
	    wcspih_naxes(naxis, i, j, alt, alts, npptr);
d858 1
a858 1
	      for (a = 0; a < *nwcs; a++) {
d860 3
a862 3
		/* apply to every alternate; these have alt == 0.   */
	        if (alt >= 'A') {
	          a = alts[alt-'A'+1];
d866 2
a867 2
	        if (a) {
	          voff = (char *)(*wcs+a) - (char *)(*wcs);
d872 2
a873 2
	        if (ndx >= 0) {
	          wptr = *((char (**)[72])wptr) + ndx;
d876 4
a879 4
	          k = (*wcs+a)->nps++;
	          (*wcs+a)->ps[k].i = i;
	          (*wcs+a)->ps[k].m = m;
	          wptr = &((*wcs+a)->ps[k].value);
d887 4
a890 4
	        k = 0;
	        for (j = 0; j < 72; j++) {
	          if (k < j) {
	            cptr[k] = cptr[j];
d893 2
a894 2
	          if (cptr[j] == '\0') {
	            if (k) cptr[k-1] = '\0';
d896 2
a897 2
	          } else if (cptr[j] == '\'' && cptr[j+1] == '\'') {
	            j++;
d900 1
a900 1
	          k++;
d903 1
a903 1
	        if (alt) break;
d909 1
a909 1
	      sprintf(errmsg, "Internal parser ERROR, null string pointer");
d916 1
a916 2
	  /* Rule 086. */
	  sprintf(errmsg, "A string value was expected");
a921 1
	  /* Rules 087-088. */
d926 1
a926 2
	  /* Rule 089. */
	  sprintf(errmsg, "Malformed inline comment");
a930 1
	  /* Rule 090. */
d934 1
a934 4
	      if (hptr < wcspih_hdr-80) {
	        strncpy(hptr, wcspih_hdr-80, 80);
	      }
	      hptr += 80;
a943 1
	  /* Rule 091. */
d946 3
a948 6
	    if (ctrl == -1) {
	      if (hptr < wcspih_hdr-80) {
	        /* Preserve rejects. */
	        strncpy(hptr, wcspih_hdr-80, 80);
	      }
	      hptr += 80;
d951 1
a951 1
	    if (abs(ctrl) > 1) {
d960 7
a966 1
	  /* Rule 092. */
d968 3
a970 2
	  alt = ' ';
	  type = -1;
d977 1
a977 1
	  /* Rule unnumbered: End-of-input. */
d979 3
a981 2
	    if (status = wcspih_inits(alts, npv, nps, nwcs, wcs) ||
	        *nwcs == 0) {
d985 1
a985 1
	    if (abs(ctrl) > 2) {
d995 1
a995 1
	    wcspih_ncards = ncards;
d1000 2
a1001 2
	    alt = ' ';
	    type = -1;
d1006 2
d1011 2
a1012 6
	      fprintf(stderr, "%d WCS cards were rejected.\n", *nreject);
	    }
	
	    if (status = wcspih_final(alts, epoch, velref, vsource, nwcs,
	        wcs)) {
	      return status;
d1015 1
a1015 1
	    return 0;
d1022 3
a1024 3
*   Determine the number of coordinate representations (up to 27), the number
*   of coordinate axes in each, and count the number of PVi_ma and PSi_ma
*   cards in each representation.
d1027 1
a1027 1
void wcspih_naxes(int naxis, int i, int j, char alt, int alts[], int *npptr)
d1032 5
a1036 1
  int a, *ip;
d1038 3
a1040 3
  a = 0;
  if (alt != ' ') {
    a = alt - 'A' + 1;
d1043 1
a1043 1
  ip = alts + a;
d1059 1
a1059 1
    npptr[a]++;
d1077 1
a1077 1
  int a, npsmax, npvmax, status = 0;
d1082 2
a1083 2
  for (a = 0; a < 27; a++) {
    if (alts[a]) (*nwcs)++;
d1099 2
a1100 2
    for (a = 0; a < 27; a++) {
      if (alts[a]) {
d1102 3
a1104 3
        wcsnpv(npv[a]);
        wcsnps(nps[a]);
        if (status = wcsini(1, alts[a], wcsp)) {
d1109 3
a1111 2
        if (a) {
          wcsp->alt[0] = 'A' + a - 1;
d1115 1
a1115 1
        alts[a] = (*nwcs)++;
d1131 2
a1132 1
*   Interpret any VELREF cards encountered for each coordinate representation.
d1144 3
a1146 3
  static char *specsys[] = {"LSRK", "BARYCENT", "TOPOCENT",
                            "LSRD", "GEOCENTR", "SOURCE", "GALACTOC"};
  int a, i, status;
d1149 1
a1149 1
  for (a = 0; a < *nwcs; a++) {
d1151 1
a1151 1
    if (undefined((*wcs+a)->equinox) && !undefined(epoch[a])) {
d1153 1
a1153 1
      (*wcs+a)->equinox = epoch[a];
d1157 1
a1157 1
    if (velref[a]) {
d1159 4
a1162 4
      if ((*wcs+a)->specsys[0] == '\0') {
        i = velref[a]%256 - 1;
        if (0 <= i && i < 7) {
          sprintf((*wcs+a)->specsys, "%s", specsys[i]);
d1168 1
a1168 1
    if (undefined((*wcs+a)->zsource) && !undefined(vsource[a])) {
d1170 2
a1171 2
      beta = vsource[a]/c;
      (*wcs+a)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
d1174 2
a1175 2
    /* Interpret -TAB header cards. */
    if (status = wcstab(*wcs+a)) {
@


4.2.1.1
log
@WCSLIB 4.2 development branch.
@
text
@d3 1
a3 1
*   WCSLIB 4.3 - an implementation of the FITS WCS standard.
d29 1
a29 1
*   $Id: wcspih.l,v 4.2 2005/09/22 09:10:53 cal103 Exp cal103 $
@


4.2.1.2
log
@Fixed a harmless addressing error for which the OSF C compiler issued a
warning.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.1 2005/12/05 02:39:43 cal103 Exp cal103 $
d885 1
a885 1
	          wptr = (*wcs+a)->ps[k].value;
@


4.2.1.3
log
@Fixed the test for repeated blanks in the NAXIS and WCSAXES patterns.
Fixed three CCi_ma rules to allow m == 0.
Test for pass == 2 instead of *wcs (!= 0) to make the intent clearer.
Renamed variables: a -> iax, alt -> a (to accord with usage in the WCS
papers), and ndx -> idx.  Replaced k with ipx and ix, and introduced jx
for some overloaded uses of variable j.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2007, Mark Calabretta
d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.2 2005/12/16 03:28:21 cal103 Exp cal103 $
d33 1
a33 2
*   definition for extracting the WCS cards for a primary image or image
*   extension from a FITS header.
d48 2
a49 4
*   appropriately.  These structs are filled in the second pass.
*
*   The parser does not check for duplicated cards, it accepts the last
*   encountered.
d120 1
a120 1
void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr);
d129 4
a132 7
        /* Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma. */
        char a;
	int  i, j, m;

	char *cptr, errmsg[80], *hptr;
	int  altlin, alts[27], iax, idx, ipx, ix, jx, naxis, *npptr,
	     nps[27], npv[27], pass, status, type, velref[27], voff;
d138 7
a144 7
	for (iax = 0; iax < 27; iax++) {
	  alts[iax] = 0;
	  npv[iax] = 0;
	  nps[iax] = 0;
	  epoch[iax]   = UNDEFINED;
	  velref[iax]  = 0;
	  vsource[iax] = UNDEFINED;
d157 2
a158 2
	a = ' ';
	idx  = -1;
d167 1
a167 1
^NAXIS"   = "" "*{INTEGER} {
d183 1
a183 1
^WCSAXES{ALT}=" "" "*{INTEGER} {
d186 2
a187 2
	    sscanf(yytext, "WCSAXES%c= %d", &a, &i);
	    wcspih_naxes(naxis, i, 0, a, alts, 0);
d194 1
a194 1
	  if (pass == 2) vptr = (*wcs)->wcsname;
d201 1
a201 1
	  if (pass == 2) vptr = &((*wcs)->crpix);
d208 1
a208 1
	  if (pass == 2) {
d218 1
a218 1
	  if (pass == 2) {
d228 1
a228 1
	  if (pass == 2) vptr = &((*wcs)->cdelt);
d235 1
a235 1
	  if (pass == 2) {
d245 1
a245 1
	  if (pass == 2) vptr = &((*wcs)->cunit);
d252 1
a252 1
	  if (pass == 2) vptr = &((*wcs)->ctype);
d259 1
a259 1
	  if (pass == 2) vptr = &((*wcs)->crval);
d266 1
a266 1
	  if (pass == 2) vptr = &((*wcs)->cname);
d273 1
a273 1
	  if (pass == 2) vptr = &((*wcs)->crder);
d280 1
a280 1
	  if (pass == 2) vptr = &((*wcs)->csyer);
d288 1
a288 1
	  if (pass == 2) vptr = &((*wcs)->pv);
d296 1
a296 1
	  if (pass == 2) vptr = &((*wcs)->pv);
d304 1
a304 1
	  if (pass == 2) vptr = &((*wcs)->ps);
d311 1
a311 1
	  if (pass == 2) vptr = &((*wcs)->lonpole);
d318 1
a318 1
	  if (pass == 2) vptr = &((*wcs)->latpole);
d326 1
a326 1
	  if (pass == 2) vptr = (*wcs)->radesys;
d333 1
a333 1
	  if (pass == 2) vptr = (*wcs)->radesys;
d340 1
a340 1
	  if (pass == 2) vptr = &((*wcs)->equinox);
d347 1
a347 1
	  sscanf(yytext, "EPOCH%c", &a);
d349 2
a350 2
	  if (a == ' ' || relax & (WCSHDR_all | WCSHDR_EPOCHa)) {
	    if (pass == 2) {
d352 2
a353 2
	      if (a >= 'A') {
	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
d374 1
a374 1
	  if (pass == 2) vptr = &((*wcs)->restfrq);
d381 1
a381 1
	  if (pass == 2) vptr = &((*wcs)->restfrq);
d388 1
a388 1
	  if (pass == 2) vptr = &((*wcs)->restwav);
d395 1
a395 1
	  if (pass == 2) vptr = (*wcs)->specsys;
d402 1
a402 1
	  if (pass == 2) vptr = (*wcs)->ssysobs;
d409 1
a409 1
	  sscanf(yytext, "VELREF%c", &a);
d411 2
a412 2
	  if (a == ' ' || relax & (WCSHDR_all | WCSHDR_VELREFa)) {
	    if (pass == 2) {
d414 2
a415 2
	      if (a >= 'A') {
	        vptr = (void *)((int *)vptr + alts[a-'A'+1]);
d435 1
a435 1
	  if (pass == 2) vptr = &((*wcs)->velosys);
d442 1
a442 1
	  if (pass == 2) vptr = (*wcs)->ssyssrc;
d449 1
a449 1
	  sscanf(yytext, "VSOURCE%c", &a);
d452 1
a452 1
	    if (pass == 2) {
d454 2
a455 2
	      if (a >= 'A') {
	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
d474 1
a474 1
	  if (pass == 2) vptr = &((*wcs)->zsource);
d481 1
a481 1
	  if (pass == 2) vptr = (*wcs)->obsgeo;
d488 1
a488 1
	  if (pass == 2) vptr = (*wcs)->obsgeo + 1;
d495 1
a495 1
	  if (pass == 2) vptr = (*wcs)->obsgeo + 2;
d502 1
a502 1
	  if (pass == 2) vptr = (*wcs)->dateobs;
d509 1
a509 1
	  if (pass == 2) vptr = (*wcs)->dateavg;
d516 1
a516 1
	  if (pass == 2) vptr = &((*wcs)->mjdobs);
d523 1
a523 1
	  if (pass == 2) vptr = &((*wcs)->mjdavg);
d548 3
a550 3
	  sscanf(yytext, "%d%c", &i, &a);
	  if (a == ' ' || relax & (WCSHDR_all | WCSHDR_CROTAia)) {
	    idx = i - 1;
d566 2
a567 2
	  a = ' ';
	  idx = i - 1;
d581 2
a582 2
	    a = ' ';
	    idx = -1;
d602 2
a603 2
	  sscanf(yytext, "%d%c", &i, &a);
	  idx = i - 1;
d610 2
a611 2
	  a = ' ';
	  idx = i - 1;
d627 2
a628 2
	  sscanf(yytext, "%d_%d%c", &i, &j, &a);
	  if (pass == 2) {
d630 2
a631 2
	    if (a != ' ') {
	      wcsp += alts[a-'A'+1];
d634 1
a634 1
	    idx = (i-1)*(wcsp->naxis) + j - 1;
d645 3
a647 3
	  a = ' ';
	  if (pass == 2) {
	    idx = (i-1)*((*wcs)->naxis) + j - 1;
d658 3
a660 3
	    a = ' ';
	    if (pass == 2) {
	      idx = (i-1)*((*wcs)->naxis) + j - 1;
d681 1
a681 1
<CCi_ma>{I2}_{I0}{ALT}" " |
d684 1
a684 1
<CCi_ma>{I3}_{I0}{ALT} {
d686 2
a687 2
	  sscanf(yytext, "%d_%d%c", &i, &m, &a);
	  idx = -1;
d694 1
a694 1
<CCi_ma>{I4}_{I0} {
d697 2
a698 2
	  a = ' ';
	  idx = -1;
d709 2
a710 2
	  idx = -1;
	  sscanf(yytext, "%c", &a);
d722 2
a723 2
	  idx = -1;
	  a = 0;
d750 1
a750 1
	    wcspih_naxes(naxis, i, j, a, alts, npptr);
d756 1
a756 1
	      for (iax = 0; iax < *nwcs; iax++) {
d758 3
a760 3
		/* to every alternate; these have a == 0. */
	        if (a >= 'A') {
	          iax = alts[a-'A'+1];
d764 2
a765 2
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
d770 2
a771 2
	        if (idx >= 0) {
	          wptr = *((int **)wptr) + idx;
d777 1
a777 1
	        if (a) break;
d798 1
a798 1
	    wcspih_naxes(naxis, i, j, a, alts, npptr);
d804 1
a804 1
	      for (iax = 0; iax < *nwcs; iax++) {
d806 3
a808 3
		/* apply to every alternate; these have a == 0.  */
	        if (a >= 'A') {
	          iax = alts[a-'A'+1];
d812 2
a813 2
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
d818 2
a819 2
	        if (idx >= 0) {
	          wptr = *((double **)wptr) + idx;
d822 4
a825 4
	          ipx = (*wcs+iax)->npv++;
	          (*wcs+iax)->pv[ipx].i = i;
	          (*wcs+iax)->pv[ipx].m = m;
	          wptr = &((*wcs+iax)->pv[ipx].value);
d833 1
a833 1
	          (*wcs+iax)->altlin |= altlin;
d837 1
a837 1
	        if (a) break;
d858 1
a858 1
	    wcspih_naxes(naxis, i, j, a, alts, npptr);
d864 1
a864 1
	      for (iax = 0; iax < *nwcs; iax++) {
d866 3
a868 3
		/* apply to every alternate; these have a == 0.   */
	        if (a >= 'A') {
	          iax = alts[a-'A'+1];
d872 2
a873 2
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
d878 2
a879 2
	        if (idx >= 0) {
	          wptr = *((char (**)[72])wptr) + idx;
d882 4
a885 4
	          ipx = (*wcs+iax)->nps++;
	          (*wcs+iax)->ps[ipx].i = i;
	          (*wcs+iax)->ps[ipx].m = m;
	          wptr = (*wcs+iax)->ps[ipx].value;
d893 4
a896 4
	        ix = 0;
	        for (jx = 0; jx < 72; jx++) {
	          if (ix < jx) {
	            cptr[ix] = cptr[jx];
d899 2
a900 2
	          if (cptr[jx] == '\0') {
	            if (ix) cptr[ix-1] = '\0';
d902 2
a903 2
	          } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
	            jx++;
d906 1
a906 1
	          ix++;
d909 1
a909 1
	        if (a) break;
d979 1
a979 1
	  a = ' ';
d1009 1
a1009 1
	    a = ' ';
d1033 3
a1035 3
*   Determine the number of coordinate representations (up to 27) and the
*   number of coordinate axes in each, and count the number of PVi_ma and
*   PSi_ma cards in each representation.
d1038 1
a1038 1
void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr)
d1043 1
a1043 1
  int iax, *ip;
d1045 3
a1047 3
  iax = 0;
  if (a != ' ') {
    iax = a - 'A' + 1;
d1050 1
a1050 1
  ip = alts + iax;
d1066 1
a1066 1
    npptr[iax]++;
d1084 1
a1084 1
  int iax, npsmax, npvmax, status = 0;
d1089 2
a1090 2
  for (iax = 0; iax < 27; iax++) {
    if (alts[iax]) (*nwcs)++;
d1106 2
a1107 2
    for (iax = 0; iax < 27; iax++) {
      if (alts[iax]) {
d1109 3
a1111 3
        wcsnpv(npv[iax]);
        wcsnps(nps[iax]);
        if (status = wcsini(1, alts[iax], wcsp)) {
d1116 2
a1117 3
        /* Record the alternate version code. */
        if (iax) {
          wcsp->alt[0] = 'A' + iax - 1;
d1121 1
a1121 1
        alts[iax] = (*nwcs)++;
d1151 1
a1151 1
  int iax, ivf, status;
d1154 1
a1154 1
  for (iax = 0; iax < *nwcs; iax++) {
d1156 1
a1156 1
    if (undefined((*wcs+iax)->equinox) && !undefined(epoch[iax])) {
d1158 1
a1158 1
      (*wcs+iax)->equinox = epoch[iax];
d1162 1
a1162 1
    if (velref[iax]) {
d1164 4
a1167 4
      if ((*wcs+iax)->specsys[0] == '\0') {
        ivf = velref[iax]%256 - 1;
        if (0 <= ivf && ivf < 7) {
          sprintf((*wcs+iax)->specsys, "%s", specsys[ivf]);
d1173 1
a1173 1
    if (undefined((*wcs+iax)->zsource) && !undefined(vsource[iax])) {
d1175 2
a1176 2
      beta = vsource[iax]/c;
      (*wcs+iax)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
d1180 1
a1180 1
    if (status = wcstab(*wcs+iax)) {
@


4.2.1.4
log
@Parenthesised a complicated boolean expression and also assignments used as
truth values.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.3 2007/06/26 04:42:00 cal103 Exp cal103 $
d661 2
a662 2
	     ((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
	     ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
d995 2
a996 2
	    if ((status = wcspih_inits(alts, npv, nps, nwcs, wcs) ||
	         *nwcs == 0)) {
d1027 2
a1028 2
	    if ((status = wcspih_final(alts, epoch, velref, vsource, nwcs,
	         wcs))) {
d1117 1
a1117 1
        if ((status = wcsini(1, alts[iax], wcsp))) {
d1187 1
a1187 1
    if ((status = wcstab(*wcs+iax))) {
@


4.2.1.5
log
@Added machinery for preserving particular auxiliary WCS cards for negative
values of the ctrl argument.  Invoke yy_delete_buffer(YY_CURRENT_BUFFER)
before returning to avoid a 16kiB memory leak.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.4 2007/06/29 01:11:43 cal103 Exp cal103 $
d136 1
a136 1
	char *cptr, errmsg[80], *hptr, *keep;
a156 1
	keep = 0x0;
d162 1
a163 1
	i = j = m = 0;
a488 1
	  keep = wcspih_hdr - 80;
a495 1
	  keep = wcspih_hdr - 80;
a502 1
	  keep = wcspih_hdr - 80;
a509 1
	  keep = wcspih_hdr - 80;
a516 1
	  keep = wcspih_hdr - 80;
a523 1
	  keep = wcspih_hdr - 80;
a530 1
	  keep = wcspih_hdr - 80;
d950 4
a953 1
	      keep = wcspih_hdr - 80;
d967 5
a971 2
	      /* Preserve rejects. */
	      keep = wcspih_hdr - 80;
a983 7
	  if (pass == 2 && keep) {
	    if (hptr < keep) {
	      strncpy(hptr, keep, 80);
	    }
	    hptr += 80;
	  }
	
a986 1
	  keep = 0x0;
a996 1
	      yy_delete_buffer(YY_CURRENT_BUFFER);
d1027 4
a1030 1
	    status = wcspih_final(alts, epoch, velref, vsource, nwcs, wcs);
a1031 1
	    yy_delete_buffer(YY_CURRENT_BUFFER);
@


4.2.1.6
log
@Revised use of the WCSHDR_all macro.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.5 2007/07/12 00:28:04 cal103 Exp cal103 $
d356 1
a356 1
	  if (a == ' ' || relax & WCSHDR_EPOCHa) {
d418 1
a418 1
	  if (a == ' ' || relax & WCSHDR_VELREFa) {
d458 1
a458 1
	  if (relax & WCSHDR_VSOURCEa) {
d563 1
a563 1
	  if (a == ' ' || relax & WCSHDR_CROTAia) {
d592 1
a592 1
	  if (relax & WCSHDR_PROJPn) {
d668 3
a670 2
	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
@


4.2.1.7
log
@Replaced use of the obsolete term "card".
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.6 2007/08/02 04:29:43 cal103 Exp cal103 $
d33 1
a33 1
*   definition for parsing the WCS keyrecords for a primary image or image
d45 1
a45 1
*   PVi_ma and PSi_ma keywords in each representation.
d51 1
a51 1
*   The parser does not check for duplicated keywords, it accepts the last
d98 1
a98 1
#define YY_DECL int wcspih(char *header, int nkeyrec, int relax, int ctrl, \
d103 1
a103 1
	  if (wcspih_nkeyrec) { \
d107 1
a107 1
	    wcspih_nkeyrec--; \
d121 1
a121 1
int  wcspih_nkeyrec;
d154 1
a154 1
	wcspih_nkeyrec = nkeyrec;
d545 2
a546 2
	  if (wcspih_nkeyrec) {
	    sprintf(errmsg, "Illegal keyrecords following END keyrecord");
d1020 1
a1020 1
	    wcspih_nkeyrec = nkeyrec;
d1034 1
a1034 2
	      fprintf(stderr, "%d WCS keyrecords were rejected.\n",
                *nreject);
d1049 1
a1049 1
*   PSi_ma keywords in each representation.
d1152 1
a1152 2
*   Interpret any VELREF keywords encountered for each coordinate
*   representation.
d1194 1
a1194 1
    /* Interpret -TAB header keywords. */
@


4.2.1.8
log
@Implemented WCSHDR_RADECSYS.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.7 2007/08/02 04:40:35 cal103 Exp cal103 $
d332 4
a335 13
	  if (relax & WCSHDR_RADECSYS) {
	    unput(' ');
	    if (pass == 2) vptr = (*wcs)->radesys;
	    type = STRING;
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    sprintf(errmsg, "RADECSYS is non-standard, use RADESYSa");
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
@


4.2.1.9
log
@Recognize ctrl == -11 which does the same as ctrl == -1 except that it
preserves {DATE,MJD}-{OBS,AVG} and OBSGEO-{X,Y,Z}.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.8 2007/08/03 01:28:53 cal103 Exp cal103 $
d499 1
a499 1
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d507 1
a507 1
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d515 1
a515 1
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d523 1
a523 1
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d531 1
a531 1
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d539 1
a539 1
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d547 1
a547 1
	  if (ctrl < -10) keep = wcspih_hdr - 80;
d979 1
a979 1
	    if (ctrl%10 == -1) {
d984 1
a984 1
	    if (abs(ctrl%10) > 1) {
d1019 1
a1019 1
	    if (abs(ctrl%10) > 2) {
@


4.2.1.10
log
@Simplified error messaging by using pointers to constant character strings.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.9 2007/08/03 05:17:55 cal103 Exp cal103 $
d136 1
a136 1
	char *cptr, *errmsg, errtxt[80], *hptr, *keep;
a180 1
	    errmsg = errtxt;
d339 1
a339 1
	    errmsg = "RADECSYS is non-standard, use RADESYSa";
d378 2
a379 1
	    errmsg = "EPOCH keyword may not have an alternate version code";
d440 2
a441 1
	    errmsg = "VELREF keyword may not have an alternate version code";
d480 1
a480 1
	    errmsg = "Deprecated VSOURCEa keyword rejected";
d555 1
a555 1
	    errmsg = "Illegal keyrecords following END keyrecord";
d577 2
a578 1
	    errmsg = "CROTAn keyword may not have an alternate version code";
d609 1
a609 1
	    errmsg = "Defunct PROJPn keyword rejected";
a686 1
            errmsg = errtxt;
a757 1
	    errmsg = errtxt;
d765 1
a765 1
	  errmsg = "Invalid KEYWORD = VALUE syntax";
d805 1
a805 1
	      errmsg = "Internal parser ERROR, null int pointer";
d813 1
a813 1
	  errmsg = "An integer value was expected";
d865 1
a865 1
	      errmsg = "Internal parser ERROR, null float pointer";
d873 1
a873 1
	  errmsg = "A floating-point value was expected";
d937 1
a937 1
	      errmsg = "Internal parser ERROR, null string pointer";
d945 1
a945 1
	  errmsg = "A string value was expected";
d957 1
a957 1
	  errmsg = "Malformed inline comment";
@


4.2.1.11
log
@Put the rules for the auxiliary WCS keywords in alphabetical order to make
them easier to find.  Removed the high-maintenance rule numbering and the
debug output implemented via YY_USER_ACTION since flex's '--debug' option
provides what we need.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.10 2007/08/03 09:02:47 cal103 Exp cal103 $
d114 5
d175 1
d192 1
d200 7
d208 1
d215 1
d225 1
d235 1
d242 1
d252 1
d259 1
d266 1
d272 5
a276 4
^LONPOLE {
	  if (pass == 2) vptr = &((*wcs)->lonpole);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
d279 3
a281 2
^LATPOLE {
	  if (pass == 2) vptr = &((*wcs)->latpole);
d283 1
a283 1
	  BEGIN(CCCCCCCa);
d286 3
a288 2
^RESTFRQ {
	  if (pass == 2) vptr = &((*wcs)->restfrq);
d290 1
a290 14
	  BEGIN(CCCCCCCa);
	}

^RESTFREQ {
	  unput(' ');
	  if (pass == 2) vptr = &((*wcs)->restfrq);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
	}

^RESTWAV {
	  if (pass == 2) vptr = &((*wcs)->restwav);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
d294 1
d302 1
d310 1
d317 5
a321 4
^CNAME	{
	  if (pass == 2) vptr = &((*wcs)->cname);
	  type = STRING;
	  BEGIN(CCCCCia);
d324 3
a326 2
^CRDER	{
	  if (pass == 2) vptr = &((*wcs)->crder);
d328 1
a328 1
	  BEGIN(CCCCCia);
d331 15
a345 4
^CSYER	{
	  if (pass == 2) vptr = &((*wcs)->csyer);
	  type = FLOAT;
	  BEGIN(CCCCCia);
d348 3
a350 2
^DATE-AVG {
	  if (pass == 2) vptr = (*wcs)->dateavg;
d352 1
a352 2
	  if (ctrl < -10) keep = wcspih_hdr - 80;
	  BEGIN(CCCCCCCC);
d355 5
a359 5
^DATE-OBS {
	  if (pass == 2) vptr = (*wcs)->dateobs;
	  type = STRING;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
	  BEGIN(CCCCCCCC);
d363 1
d387 4
a390 2
^EQUINOX {
	  if (pass == 2) vptr = &((*wcs)->equinox);
d395 3
a397 2
^MJD-AVG" " {
	  if (pass == 2) vptr = &((*wcs)->mjdavg);
d399 1
a399 2
	  if (ctrl < -10) keep = wcspih_hdr - 80;
	  BEGIN(CCCCCCCC);
d402 3
a404 23
^MJD-OBS" " {
	  if (pass == 2) vptr = &((*wcs)->mjdobs);
	  type = FLOAT;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-X {
	  if (pass == 2) vptr = (*wcs)->obsgeo;
	  type = FLOAT;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-Y {
	  if (pass == 2) vptr = (*wcs)->obsgeo + 1;
	  type = FLOAT;
	  if (ctrl < -10) keep = wcspih_hdr - 80;
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-Z {
	  if (pass == 2) vptr = (*wcs)->obsgeo + 2;
a405 7
	  if (ctrl < -10) keep = wcspih_hdr - 80;
	  BEGIN(CCCCCCCC);
	}

^RADESYS {
	  if (pass == 2) vptr = (*wcs)->radesys;
	  type = STRING;
a408 16
^RADECSYS {
	  if (relax & WCSHDR_RADECSYS) {
	    unput(' ');
	    if (pass == 2) vptr = (*wcs)->radesys;
	    type = STRING;
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "RADECSYS is non-standard, use RADESYSa";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

d410 1
d417 1
a422 12
^SSYSSRC {
	  if (pass == 2) vptr = (*wcs)->ssyssrc;
	  type = STRING;
	  BEGIN(CCCCCCCa);
	}

^VELOSYS {
	  if (pass == 2) vptr = &((*wcs)->velosys);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
	}

d424 1
d448 14
d463 1
d487 42
a528 2
^WCSNAME {
	  if (pass == 2) vptr = (*wcs)->wcsname;
d530 10
a539 1
	  BEGIN(CCCCCCCa);
d542 3
a544 2
^ZSOURCE {
	  if (pass == 2) vptr = &((*wcs)->zsource);
d546 2
a547 1
	  BEGIN(CCCCCCCa);
d551 1
d562 1
d567 53
d622 1
d629 1
d637 1
d647 1
d664 1
d674 1
a674 1
	  /* This covers the defunct forms CD00i00j and PC00i00j. */
d696 1
a699 44
<CROTAi>{I1}{ALT}" " |
<CROTAi>{I2}{ALT} {
	  sscanf(yytext, "%d%c", &i, &a);
	  if (a == ' ' || relax & WCSHDR_CROTAia) {
	    idx = i - 1;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "CROTAn keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

<CROTAi>{I3} {
	  sscanf(yytext, "%d", &i);
	  a = ' ';
	  idx = i - 1;
	  BEGIN(VALUE);
	}

<CROTAi>. {
	  BEGIN(DISCARD);
	}

<CCCCCCCa>{ALT} {
	  idx = -1;
	  sscanf(yytext, "%c", &a);
	  BEGIN(VALUE);
	}

<CCCCCCCa>. {
	  BEGIN(DISCARD);
	}

<CCCCCCCC>. {
	  unput(yytext[0]);
	  idx = -1;
	  a = 0;
	  BEGIN(VALUE);
	}

d706 1
d716 1
d724 1
d728 5
a732 15
<PROJPn>{I0}"  " {
	  if (relax & WCSHDR_PROJPn) {
	    sscanf(yytext, "%d", &m);
	    i = 0;
	    a = ' ';
	    idx = -1;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "Defunct PROJPn keyword rejected";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d735 2
a736 1
<PROJPn>. {
d740 8
d749 1
d764 1
d770 1
d812 1
d818 1
d872 1
d878 1
d944 1
d951 1
d956 1
d962 1
d976 1
d993 1
d1011 1
a1011 1
	  /* End-of-input. */
@


4.2.1.12
log
@Renamed type -> valtype; set valtype and vptr as the first two jobs in each
keyword-matching rule.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.11 2007/12/03 07:21:00 cal103 Exp cal103 $
d130 1
a130 1
	
d133 1
a133 1
	     nps[27], npv[27], pass, status, valtype, velref[27], voff;
d161 1
a161 1
	valtype = -1;
a193 1
	  valtype = FLOAT;
d195 1
d200 5
a204 3
	  valtype = FLOAT;
	  if (pass == 2) vptr = &((*wcs)->pc);
	  altlin = 1;
d209 5
a213 3
	  valtype = FLOAT;
	  if (pass == 2) vptr = &((*wcs)->cd);
	  altlin = 2;
a217 1
	  valtype = FLOAT;
d219 1
d224 5
a228 3
	  valtype = FLOAT;
	  if (pass == 2) vptr = &((*wcs)->crota);
	  altlin = 4;
a232 1
	  valtype = STRING;
d234 1
a238 1
	  valtype = STRING;
d240 1
a244 1
	  valtype = FLOAT;
d246 1
a250 1
	  valtype = FLOAT;
d252 1
a256 1
	  valtype = FLOAT;
d258 1
a262 1
	  valtype = FLOAT;
d264 1
d269 1
a269 1
	  valtype = FLOAT;
d271 1
a271 1
	  unput(' ');
a275 1
	  valtype = FLOAT;
d277 1
d282 1
a282 1
	  valtype = FLOAT;
d284 1
a284 1
	  npptr = npv;
d289 1
a289 1
	  valtype = FLOAT;
d291 1
a291 1
	  npptr = npv;
d296 1
a296 1
	  valtype = STRING;
d298 1
a298 1
	  npptr = nps;
a302 1
	  valtype = STRING;
d304 1
a308 1
	  valtype = FLOAT;
d310 1
a314 1
	  valtype = FLOAT;
d316 1
a320 1
	  valtype = STRING;
d322 1
a327 1
	  valtype = STRING;
d329 1
a337 1
	    valtype = FLOAT;
d346 1
a358 1
	  valtype = FLOAT;
d360 1
a364 1
	  valtype = FLOAT;
d366 1
a371 1
	  valtype = FLOAT;
d373 1
a378 1
	  valtype = FLOAT;
d380 1
a385 1
	  valtype = FLOAT;
d387 1
a392 1
	  valtype = FLOAT;
d394 1
a399 1
	  valtype = STRING;
d401 1
d407 1
a407 1
	    valtype = STRING;
d409 1
a409 1
	    unput(' ');
a421 1
	  valtype = STRING;
d423 1
a427 1
	  valtype = STRING;
d429 1
a433 1
	  valtype = STRING;
d435 1
a439 1
	  valtype = FLOAT;
d441 1
a448 1
	    valtype = INTEGER;
d457 1
a472 1
	    valtype = FLOAT;
d481 1
a493 1
	  valtype = STRING;
d495 1
a499 1
	  valtype = FLOAT;
d501 1
d580 1
a580 1
	    errmsg = errtxt;
d685 1
a685 1
	  if (valtype == INTEGER) {
d687 1
a687 1
	  } else if (valtype == FLOAT) {
d689 1
a689 1
	  } else if (valtype == STRING) {
d693 1
a693 2
	    sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
              valtype);
d713 1
a713 1
	        /* to every alternate; these have a == 0. */
d759 1
a759 1
	        /* apply to every alternate; these have a == 0.  */
d817 1
a817 1
	        /* apply to every alternate; these have a == 0.   */
d926 1
a926 1
	  valtype = -1;
d936 2
a937 2
	    if ((status = wcspih_inits(alts, npv, nps, nwcs, wcs)) ||
	         *nwcs == 0) {
d958 1
a958 1
	    valtype = -1;
d967 1
a967 1
	        *nreject);
@


4.2.1.13
log
@Reworked the prologue notes.  Added brief comments describing the variables
used.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.12 2007/12/03 07:42:08 cal103 Exp cal103 $
d32 3
a34 3
*   wcspih.l is a Flex description file containing the definition of a lexical
*   scanner for parsing the WCS keyrecords from a FITS primary image or image
*   extension header.
d36 1
a36 2
*   wcspih.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a
*   description of the user interface and operating notes.
d38 2
a39 14
*   Implementation notes
*   --------------------
*   Because the WCSAXESa keyword is not mandatory, its default value of "the
*   larger of NAXIS and the largest index of these keywords [CRPIXj, PCi_j or
*   CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS header"
*   effectively invalidates the use of NAXIS for determining the number of
*   coordinate axes and forces a preliminary pass through the header to
*   determine the "largest index" in headers where WCSAXESa was omitted.
*   Also since the use of WCSAXESa is optional there is no way to determine
*   the number of coordinate representations (the "a" value) other than by
*   parsing all of the WCS keywords in the header; even if WCSAXESa is
*   specified for some representations it cannot be known in advance whether
*   it was specified for all of those present in the header.  Hence the
*   scanner must be implemented in two passes.
d41 5
a45 6
*   The first pass is used to determine the number of coordinate
*   representations (up to 27) and the number of coordinate axes in each.
*   Effectively WCSAXESa is ignored unless it exceeds the "largest index" in
*   which case the keywords for the extra axes assume their default values.
*   The number of PVi_ma and PSi_ma keywords in each representation is also
*   counted in the first pass.
d127 2
a128 2
	/* Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma. */
	char a;
a147 1
	/* Parameters used to implement YY_INPUT. */
a150 1
	/* Our handle on the input stream. */
d154 2
d157 2
a158 1
	/* Keyword parameters. */
d160 1
a160 3
	a = ' ';
	
	/* For decoding the keyvalue. */
a161 4
	idx     = -1;
	vptr    = 0x0;
	
	/* For keywords that require special handling. */
d163 2
a164 1
	npptr  = 0x0;
a165 5
	/* The data structures produced. */
	*nwcs = 0;
	*wcs  = 0x0;
	
	pass = 1;
@


4.2.1.14
log
@Do checks on i, k & m in <VALUE>.  Added a rule for VELANGLa.
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.13 2007/12/03 07:50:12 cal103 Exp cal103 $
a455 6
^VELANGL {
	  valtype = FLOAT;
	  if (pass == 2) vptr = &((*wcs)->velangl);
	  BEGIN(CCCCCCCa);
	}

a544 1
	  /* Invalid axis number will be caught by <VALUE>. */
d546 2
d558 3
a560 1
<CCi_ja>{I2}_{I2}{ALT} {
a572 2
<CCi_ja>{I1}_{I3}{ALT} |
<CCi_ja>{I3}_{I1}{ALT} |
a576 1
	  /* Invalid axis number will be caught by <VALUE>. */
d578 4
d658 3
a660 1
<CCi_ma>{I2}_{I2}{ALT} {
a665 2
<CCi_ma>{I1}_{I3}{ALT} |
<CCi_ma>{I3}_{I0}{ALT} |
a669 1
	  /* Invalid parameter will be caught by <VALUE>. */
d671 2
d702 6
a707 16
	  /* Do checks on i, k & m. */
	  if (i > 99 || j > 99 || m > 99) {
	    if (relax & WCSHDR_reject) {
	      errmsg = errtxt;
	      if (i > 99 || j > 99) {
	        sprintf(errmsg, "Axis number exceeds 99");
	      } else if (m > 99) {
	        sprintf(errmsg, "Parameter number exceeds 99");
	      }
	      BEGIN(ERROR);
	
	    } else {
	      /* Pretend we don't recognize it. */
	      BEGIN(DISCARD);
	    }
	
d709 4
a712 12
	    if (valtype == INTEGER) {
	      BEGIN(INTEGER_VAL);
	    } else if (valtype == FLOAT) {
	      BEGIN(FLOAT_VAL);
	    } else if (valtype == STRING) {
	      BEGIN(STRING_VAL);
	    } else {
	      errmsg = errtxt;
	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
	        valtype);
	      BEGIN(ERROR);
	    }
@


4.2.1.15
log
@Important bug fix in wcspih_naxes(): check for a == 0 (indication of a
keyword that applies to all alternates).  Combined the '<CCCCCCCa>{ALT}'
and '<CCCCCCCC>.' rules.  Eliminated unnecessary calls to yyless().
@
text
@d29 1
a29 1
*   $Id: wcspih.l,v 4.2.1.14 2007/12/03 08:07:22 cal103 Exp cal103 $
d203 1
d529 1
d539 1
d640 1
a640 2
<CCCCCCCa>{ALT} |
<CCCCCCCC>. {
d642 1
a642 7
	
	  if (YY_START == CCCCCCCa) {
	    sscanf(yytext, "%c", &a);
	  } else {
	    unput(yytext[0]);
	    a = 0;
	  }
d650 7
d703 1
a703 1
	  /* Do checks on i, j & m. */
a1028 4
  if (a == 0) {
    return;
  }

d1135 2
a1136 2
  const char *specsys[] = {"LSRK", "BARYCENT", "TOPOCENT",
                           "LSRD", "GEOCENTR", "SOURCE", "GALACTOC"};
@


4.2.1.16
log
@Switched to LGPL 3.0.
@
text
@d2 28
a29 30

    WCSLIB 4.3 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2007, Mark Calabretta

    This file is part of WCSLIB.

    WCSLIB is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the
    Free Software Foundation, either version 3 of the License, or (at your
    option) any later version.

    WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
    more details.

    You should have received a copy of the GNU Lesser General Public License
    along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

    Correspondence concerning WCSLIB may be directed to:
       Internet email: mcalabre@@atnf.csiro.au
       Postal address: Dr. Mark Calabretta
                       Australia Telescope National Facility, CSIRO
                       PO Box 76
                       Epping NSW 1710
                       AUSTRALIA

    Author: Mark Calabretta, Australia Telescope National Facility
    http://www.atnf.csiro.au/~mcalabre/index.html
    $Id: wcspih.l,v 4.2.1.15 2007/12/03 08:16:53 cal103 Exp cal103 $
@


4.2.1.17
log
@Worked over the implementation notes a bit more.  "Inline comment" ->
"keycomment".
@
text
@d31 1
a31 1
    $Id: wcspih.l,v 4.2.1.16 2007/12/03 08:19:36 cal103 Exp cal103 $
d43 12
a54 7
*   Use of the WCSAXESa keyword is not mandatory.  Its default value is "the
*   larger of NAXIS and the largest index of these keywords [i.e. CRPIXj,
*   PCi_j or CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS
*   header".  Consequently the definition of WCSAXESa effectively invalidates
*   the use of NAXIS for determining the number of coordinate axes and forces
*   a preliminary pass through the header to determine the "largest index" in
*   headers where WCSAXESa was omitted.
d56 1
a56 8
*   Furthermore, since the use of WCSAXESa is optional, there is no way to
*   determine the number of coordinate representations (the "a" value) other
*   than by parsing all of the WCS keywords in the header; even if WCSAXESa
*   was specified for some representations it cannot be known in advance
*   whether it was specified for all of those present in the header.
*
*   Hence the definition of WCSAXESa forces the scanner must be implemented in
*   two passes.  The first pass is used to determine the number of coordinate
d919 1
a919 1
	  errmsg = "Malformed keycomment";
@


4.2.1.18
log
@In the <<EOF>> rule, return the status value from wcspih_final().
@
text
@d31 1
a31 1
    $Id: wcspih.l,v 4.2.1.17 2007/12/22 07:29:53 cal103 Exp cal103 $
a1000 2
	    yy_delete_buffer(YY_CURRENT_BUFFER);

d1008 4
a1011 1
	    return wcspih_final(alts, epoch, velref, vsource, nwcs, wcs);
@


4.2.1.19
log
@Call yylex_destroy() to free buffer memory rather than yy_delete_buffer()
as the former reinitializes global variables for subsequent calls.  Set
%option for outfile and prefix to save doing it on the flex command line.
Ensure that keyrecords following END really are ignored.
@
text
@d31 1
a31 1
    $Id: wcspih.l,v 4.2.1.18 2007/12/26 04:17:18 cal103 Exp cal103 $
a77 2
%option outfile="wcspih.c"
%option prefix="wcspih"
a154 1
        int yylex_destroy(void);
a531 1
	  yyless(0);
d533 1
a533 2
	    wcspih_nkeyrec = 0;
	    errmsg = "Keyrecords following the END keyrecord were ignored";
d976 1
a976 1
	      yylex_destroy();
d1001 1
a1001 1
	    yylex_destroy();
@


4.1
log
@WCSLIB 4.1: new interpretation of the errlvl argument, now ctrl - for
ctrl < 0 WCS cards processed by wcspih() are removed from the header;
removed support for K&R C (including via YY_USE_PROTOS); use yy_act in the
debug printout to identify the rule and numbered each rule with a comment;
add BEGIN(INITIAL) in main(); recognize DATE-AVG; restore NPVMAX and NPSMAX
to their original values in wcspih_inits(); invoke wcstab() on each wcsprm
struct in wcspih_final().
@
text
@d3 1
a3 1
*   WCSLIB 4.1 - an implementation of the FITS WCS standard.
d29 1
a29 1
*   $Id: wcspih.l,v 4.0 2005/02/04 06:18:43 cal103 Exp cal103 $
d1095 1
a1095 1
    if (!(*wcs = (struct wcsprm *)calloc(*nwcs, sizeof(struct wcsprm)))) {
@


4.0
log
@WCSLIB 4.0: changed from LGPL to GPL; macros for UNDEFINED values moved to
wcsmath.h; commented some mysterious looking code.
@
text
@d3 1
a3 1
*   WCSLIB 4.0 - an implementation of the FITS WCS standard.
d29 1
a29 1
*   $Id: wcspih.l,v 3.6 2004/08/25 04:45:50 cal103 Exp cal103 $
d95 1
a95 2
#ifdef YY_USE_PROTOS
#define YY_DECL int wcspih(char *header, int nkeys, int relax, int errlvl, \
a96 4
#else
#define YY_DECL int wcspih(header, nkeys, relax, errlvl, nreject, nwcs, wcs) \
char *header; int nkeys, relax, errlvl, *nreject, *nwcs; struct wcsprm **wcs;
#endif
d100 1
a100 1
	  if (wcspih_nkeys) { \
d104 1
a104 1
	    wcspih_nkeys--; \
d111 4
a114 2
/* Uncomment the next line to print text as it is matched. */
/* #define YY_USER_ACTION printf("%s\n", yytext); */
d116 3
a118 1
extern char *yytext;
a119 1
#ifdef YY_USE_PROTOS
a124 9
#else
void wcspih_naxes();
int  wcspih_inits();
int  wcspih_final();
#endif

/* These global variables are required by YY_INPUT. */
char *wcspih_hdr;
int  wcspih_nkeys;
d130 1
a130 2
%{
	char alt, *cptr, errmsg[80];
d136 1
a136 1

d146 1
a146 1

d148 3
a150 2
	wcspih_nkeys = nkeys;

d153 2
a154 2
	*wcs  = 0;

d161 5
a165 3
	npptr = 0;
	vptr  = 0;
%}
d168 1
d172 1
a172 1

d178 2
a179 1
	    BEGIN(FLUSH);
d184 1
d193 1
d200 1
d207 1
d217 1
d227 1
d234 1
d244 1
d251 1
d258 1
d265 1
d272 1
d279 1
d286 1
d294 1
d302 1
d310 1
d317 1
d324 1
d332 1
d339 1
d346 1
d348 1
a348 1

d356 1
a356 1

d360 1
a360 1

d365 1
a365 1

d372 1
d380 1
d387 1
d394 1
d401 1
d408 1
d410 1
a410 1

d418 1
a418 1

d422 1
a422 1

d427 1
a427 1

d434 1
d441 1
d448 1
d450 1
a450 1

d458 1
a458 1

d462 1
a462 1

d464 1
a464 1
            sprintf(errmsg, "Deprecated VSOURCEa keyword rejected");
d466 1
a466 1

d473 1
d480 1
d487 1
d494 1
d501 1
d507 7
d515 1
d522 1
d529 3
a531 1
	  if (wcspih_nkeys) {
d535 1
a535 1
	    BEGIN(FLUSH);
d539 5
a543 1
^.	BEGIN(DISCARD);
d547 1
d552 1
a552 1

d557 1
a557 1

d564 1
d572 1
d577 1
d584 1
a584 1

d588 1
a588 1

d595 1
d601 1
d608 1
d616 1
d626 1
d633 1
a633 1

d643 1
d653 1
a653 1
	  /* This covers the defunct forms CD00i00j and PC00i00j. */
d663 1
a663 1

d668 1
a668 1

d675 1
d685 1
d695 1
d703 1
d708 1
d715 1
d720 1
d728 1
d742 1
d748 1
d752 1
a752 1

d762 1
a762 1

d768 1
a768 1

d773 1
a773 1

d776 1
a776 1

d779 1
a779 1

d781 1
a781 1

d790 1
d796 1
d800 1
a800 1

d810 1
a810 1

d816 1
a816 1

d820 1
a820 1

d827 1
a827 1

d830 1
a830 1

d836 1
a836 1

d839 1
a839 1

d841 1
a841 1

d850 1
d856 1
d860 1
a860 1

d870 1
a870 1

d876 1
a876 1

d880 1
a880 1

d887 1
a887 1

d891 1
a891 1

d898 1
a898 1

d905 1
a905 1

d908 1
a908 1

d911 1
a911 1

d913 1
a913 1

d922 1
d929 1
d934 1
d940 12
a951 2
	  if (pass == 2 && errlvl > 2) {
	    fprintf(stderr, "%.80s\n  Discarded.\n", wcspih_hdr-80);
d957 1
d959 13
a971 3
	  if (pass == 2 && errlvl > 1) {
	    fprintf(stderr, "%.80s\n%4d: %s.\n", wcspih_hdr-80, *nreject,
	      errmsg);
d977 1
d982 1
a982 1
	  npptr = 0;
d987 1
d993 2
a994 2

	    if (errlvl > 2) {
d1002 1
a1002 1

d1004 1
a1004 1
	    wcspih_nkeys = nkeys;
d1006 1
a1006 1

d1011 1
a1011 1

d1013 1
a1013 1

d1015 3
a1017 1
	    if (errlvl == 1) {
d1020 6
a1025 3

	    wcspih_final(alts, epoch, velref, vsource, nwcs, wcs);

a1031 1

d1038 1
a1038 5
void wcspih_naxes(naxis, i, j, alt, alts, npptr)

int naxis, i, j;
char alt;
int alts[], *npptr;
d1076 6
a1081 4
int wcspih_inits(alts, npv, nps, nwcs, wcs)

int alts[], npv[], nps[], *nwcs;
struct wcsprm **wcs;
d1084 1
a1084 1
  int a, status;
d1099 4
d1113 1
a1113 1
          return status;
d1126 4
d1132 1
a1132 1
  return 0;
d1140 7
a1146 8
int wcspih_final(alts, epoch, velref, vsource, nwcs, wcs)

int alts[];
double epoch[];
int velref[];
double vsource[];
int *nwcs;
struct wcsprm **wcs;
d1151 1
a1151 1
  int a, i;
d1177 6
@


3.6
log
@WCSLIB 3.6: A number of fixes:

  1) Fixed handling of string-valued keywords where the inline comment
     contains a single-quote character (').

  2) Fixed the address arithmetic for EPOCH and VELREF.

  3) Translate VSOURCEa into ZSOURCEa if required.

  4) Recognize SSYSSRCa.

  5) Support free-format string keyvalues, as well as integer and floating-
     point keyvalues; documented this in the prologue of wcshdr.h.

  6) Allow header cards without inline comments.

  7) Fixed function prototyping in wcspih.l (i.e. ANSI and non-ANSI forms were
     potentially mixed).

  8) Catch an unhandled newline character on the END card that was echoed
     to stdout.

  9) In error messages, print "ERROR" (uppercase) - POSIX standard.
@
text
@d3 2
a4 2
*   WCSLIB 3.6 - an implementation of the FITS WCS convention.
*   Copyright (C) 1995-2004, Mark Calabretta
d6 13
a18 13
*   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., 675 Mass Ave, Cambridge, MA 02139, USA.
d29 1
a29 1
*   $Id: wcspih.l,v 3.5 2004/06/28 04:28:33 mcalabre Exp mcalabre $
d42 3
a44 3
*   required to determine the number coordinate representations (up to 27) and
*   the number of coordinate axes in each; it also counts the number of PVi_ma
*   and PSi_ma cards in each representation.
d89 1
a89 3

#define UNDEFINED 987654321.0e99
#define undefined(value) (value == UNDEFINED)
d693 2
d739 2
d797 2
@


3.5
log
@WCSLIB 3.5: initial revision.
@
text
@d3 1
a3 1
*   WCSLIB 3.5 - an implementation of the FITS WCS convention.
d29 1
a29 1
*   $Id$
d37 3
a50 2
*   Refer to wcshdr.h for a description of the user interface.
*
d71 1
a71 1
STRING	'.*/'[^']
a77 1
%x ENDQUOTE
d82 1
d123 1
d127 7
a133 2
int  wcspih_final(int alts[], double epoch[], int velref[], int *nwcs,
                  struct wcsprm **wcs);
d147 1
a147 1
	double epoch[27];
d156 3
a158 2
	  epoch[a]  = UNDEFINED;
	  velref[a] = 0;
a332 1
^EPOCH"   " |
d340 1
a340 1
	        vptr += alts[alt-'A'+1];
a388 1
^VELREF"  " |
d396 1
a396 1
	        vptr += alts[alt-'A'+1];
d420 3
a422 3
^VSOURCE {
	  if (*wcs) vptr = &((*wcs)->vsource);
	  type = FLOAT;
d426 24
d496 2
d668 1
a668 1
<VALUE>=" " {
d676 1
a676 1
	    sprintf(errmsg, "Internal parser error, bad data type: %d", type);
d686 1
a686 1
<INTEGER_VAL>" "*{INTEGER} {
d719 1
a719 1
	      sprintf(errmsg, "Internal parser error, null int pointer");
d730 1
a730 1
<FLOAT_VAL>" "*{FLOAT} {
d775 1
a775 1
	      sprintf(errmsg, "Internal parser error, null float pointer");
d786 1
a786 1
<STRING_VAL>'.*/'[^'] {
a825 1
	          k++;
d828 1
d833 2
d840 1
a840 1
	      BEGIN(ENDQUOTE);
d843 1
a843 1
	      sprintf(errmsg, "Internal parser error, null string pointer");
d854 2
a855 5
<ENDQUOTE>' {
	  BEGIN(COMMENT);
	}

<COMMENT>" "*\/.* {
d889 1
a889 1
<<EOF>>	{
d921 1
a921 1
            wcspih_final(alts, epoch, velref, nwcs, wcs);
d931 3
a933 3
*   Determine the number coordinate representations (up to 27), the number of
*   coordinate axes in each, and count the number of PVi_ma and PSi_ma cards
*   in each representation.
d1032 1
a1032 1
int wcspih_final(alts, epoch, velref, nwcs, wcs)
d1036 3
a1038 1
int velref[], *nwcs;
d1045 1
d1063 1
d1065 5
@


0.0
log
@Empty revision
@
text
@d1 1034
@
