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	0.0;

0.0
date	2007.07.11.02.03.48;	author cal103;	state Exp;
branches
	0.0.1.1;
next	;

0.0.1.1
date	2007.07.11.02.05.52;	author cal103;	state Exp;
branches;
next	0.0.1.2;

0.0.1.2
date	2007.08.02.04.34.40;	author cal103;	state Exp;
branches;
next	0.0.1.3;

0.0.1.3
date	2007.08.02.04.49.30;	author cal103;	state Exp;
branches;
next	0.0.1.4;

0.0.1.4
date	2007.12.03.06.20.44;	author cal103;	state Exp;
branches;
next	0.0.1.5;

0.0.1.5
date	2007.12.22.12.59.48;	author cal103;	state Exp;
branches;
next	0.0.1.6;

0.0.1.6
date	2007.12.26.04.10.30;	author cal103;	state Exp;
branches;
next	0.0.1.7;

0.0.1.7
date	2007.12.27.05.11.41;	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.42.20;	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.51.49;	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.32.16;	author cal103;	state Exp;
branches;
next	;

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

4.5.1.2
date	2010.11.15.06.55.27;	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.25.14;	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.7.1.2;

4.7.1.2
date	2011.08.15.03.18.17;	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.23.43;	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.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.41.24;	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.52.32;	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.4.1.1
date	2015.04.21.14.44.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.6.1.1
date	2015.06.14.07.14.44;	author mcalabre;	state Exp;
branches;
next	;

5.7.1.1
date	2015.06.29.02.47.24;	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.10.1.1
date	2015.10.09.08.22.35;	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.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.13.30.44;	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.46.39;	author mcalabre;	state Exp;
branches;
next	5.17.1.4;

5.17.1.4
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.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.35.42;	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.11.53;	author mcalabre;	state Exp;
branches;
next	6.4.1.3;

6.4.1.3
date	2019.12.31.02.27.13;	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.03.02.49.52;	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.42.40;	author mcalabre;	state Exp;
branches;
next	7.4.1.3;

7.4.1.3
date	2021.02.25.14.07.35;	author mcalabre;	state Exp;
branches;
next	7.4.1.4;

7.4.1.4
date	2021.02.25.14.12.20;	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.6.1.2;

7.6.1.2
date	2021.07.02.08.32.59;	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.56.40;	author mcalabre;	state Exp;
branches;
next	;


desc
@Flex description file containing a lexical scanner definition for extracting
the WCS cards from a FITS binary table 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: wcsbth.l,v 8.6.1.2 2026/04/10 03:56:40 mcalabre Exp mcalabre $
*=============================================================================
*
* wcsbth.l is a Flex description file containing the definition of a lexical
* scanner for parsing the WCS keyrecords for one or more image arrays and/or
* pixel lists in a FITS binary table header.  It can also handle primary image
* and image extension headers.
*
* wcsbth.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
* of the user interface and operating notes.
*
* Implementation notes
* --------------------
* wcsbth() may be invoked with an option that causes it to recognize the
* image-header form of WCS keywords as defaults for each alternate coordinate
* representation (up to 27).  By design, with this option enabled wcsbth() can
* also handle primary image and image extension headers, effectively treating
* them as a single-column binary table though with WCS keywords of a different
* form.
*
* NAXIS is always 2 for binary tables, it refers to the two-dimensional nature
* of the table.  Thus NAXIS does not count the number of image axes in either
* image arrays or pixels lists and for the latter there is not even a formal
* equivalent of WCSAXESa.  Hence NAXIS is always ignored and a first pass
* through the header is required to determine the number of images, the number
* of alternate coordinate representations for each image (up to 27), and the
* number of coordinate axes in each representation; this pass also counts the
* number of iPVn_ma and iPSn_ma or TVk_ma and TSk_ma keywords in each
* representation.
*
* On completion of the first pass, the association between column number and
* axis number is defined for each representation of a pixel list.  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.
*
* It is permissible for a scalar table column to contain degenerate (single-
* point) image arrays and simultaneously form one axis of a pixel list.
*
* The parser does not check for duplicated keywords, for most keywords it
* accepts the last encountered.
*
* wcsbth() does not currently handle the Green Bank convention.
*
*===========================================================================*/

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

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

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	'([^']|'')*'

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

/* Exclusive start states. */
%x CCCCCia   iCCCna iCCCCn    TCCCna TCCCCn
%x CCi_ja    ijCCna           TCn_ka TCCn_ka
%x CROTAi           iCROTn           TCROTn
%x CCi_ma    iCn_ma iCCn_ma   TCn_ma TCCn_ma
%x PROJPm
%x CCCCCCCC CCCCCCCa
%x CCCCna   CCCCCna
%x CCCCn    CCCCCn
%x VALUE INTEGER_VAL FLOAT_VAL FLOAT2_VAL STRING_VAL
%x COMMENT DISCARD ERROR FLUSH

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

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

			// Codes used for keyvalue data types.
#define INTEGER 0
#define FLOAT   1
#define FLOAT2  2
#define STRING  3

			// Bit masks used for keyword types:
#define IMGAUX  0x1	// Auxiliary image header, e.g. LONPOLEa or
			// DATE-OBS.
#define IMGAXIS 0x2	// Image header with axis number, e.g.
			// CTYPEia.
#define IMGHEAD 0x3	// IMGAUX | IMGAXIS, i.e. image header of
			// either type.
#define BIMGARR 0x4	// Binary table image array, e.g. iCTYna.
#define PIXLIST 0x8	// Pixel list, e.g. TCTYna.
#define BINTAB  0xC	// BIMGARR | PIXLIST, i.e. binary table
			// image array (without axis number) or
			// pixel list, e.g. LONPna or OBSGXn.

// User data associated with yyscanner.
struct wcsbth_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 wcsbth_scanner(char *header, int nkeyrec, int relax, \
 int ctrl, int keysel, int *colsel, 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);

// A convenience macro to get around incompatibilities between unput() and
// yyless(): put yytext followed by a blank back onto the input stream.
#define WCSBTH_PUTBACK \
  snprintf(strtmp, 80, "%s ", yytext); \
  size_t iz = strlen(strtmp); \
  while (iz) unput(strtmp[--iz]);

// Struct used internally for header bookkeeping.
struct wcsbth_alts {
  int ncol, ialt, icol, imgherit;
  short int (*arridx)[27];
  short int pixidx[27];
  short int pad1;
  unsigned int *pixlist;

  unsigned char (*npv)[27];
  unsigned char (*nps)[27];
  unsigned char pixnpv[27];
  unsigned char pixnps[27];
  unsigned char pad2[2];
};

// Internal helper functions.
static YY_DECL;
static int wcsbth_colax(struct wcsprm *wcs, struct wcsbth_alts *alts, int k,
        char a);
static int wcsbth_final(struct wcsbth_alts *alts, int *nwcs,
        struct wcsprm **wcs);
static struct wcsprm *wcsbth_idx(struct wcsprm *wcs, struct wcsbth_alts *alts,
        int keytype, int n, char a);
static int wcsbth_init1(struct wcsbth_alts *alts, int auxprm, int *nwcs,
        struct wcsprm **wcs);
static int wcsbth_pass1(int keytype, int i, int j, int n, int k, char a,
        char ptype, struct wcsbth_alts *alts);

// Helper functions for keywords that require special handling.
static int wcsbth_jdref(double *wptr,   const double *jdref);
static int wcsbth_jdrefi(double *wptr,  const double *jdrefi);
static int wcsbth_jdreff(double *wptr,  const double *jdreff);
static int wcsbth_epoch(double *wptr,   const double *epoch);
static int wcsbth_vsource(double *wptr, const double *vsource);

// Helper functions for keyvalue validity checking.
static int wcsbth_timepixr(double timepixr);

%}

%%
	char *errmsg, errtxt[80], *keyname, strtmp[80];
	int    inttmp;
	double dbltmp, dbl2tmp[2];
	struct auxprm auxtem;
	struct wcsprm wcstem;
	
	// Initialize returned values.
	*nreject = 0;
	*nwcs = 0;
	*wcs  = 0x0;
	
	// Our handle on the input stream.
	char *keyrec = header;
	char *hptr = header;
	char *keep = 0x0;
	
	// For keeping tallies of keywords found.
	int nvalid = 0;
	int nother = 0;
	
	// Used to flag image header keywords that are always inherited.
	int imherit = 1;
	
	// If strict, then also reject.
	if (relax & WCSHDR_strict) relax |= WCSHDR_reject;
	
	// Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka.
	int i = 0;
	int j = 0;
	int k = 0;
	int n = 0;
	int m = 0;
	char a = ' ';
	
	// Header bookkeeping.
	struct wcsbth_alts alts;
	alts.ncol = 0;
	alts.arridx  = 0x0;
	alts.pixlist = 0x0;
	alts.npv = 0x0;
	alts.nps = 0x0;
	
	for (int ialt = 0; ialt < 27; ialt++) {
	  alts.pixidx[ialt] = 0;
	  alts.pixnpv[ialt] = 0;
	  alts.pixnps[ialt] = 0;
	}
	
	// For decoding the keyvalue.
	int keytype =  0;
	int valtype = -1;
	void *vptr  = 0x0;
	
	// For keywords that require special handling.
	int altlin = 0;
	char ptype = ' ';
	int (*chekval)(double) = 0x0;
	int (*special)(double *, const double *) = 0x0;
	struct auxprm *auxp = 0x0;
	int auxprm = 0;
	int naux   = 0;
	
	// Selection by column number.
	int nsel = colsel ? colsel[0] : 0;
	int incl = (nsel > 0);
	char exclude[1000];
	for (int icol = 0; icol < 1000; icol++) {
	  exclude[icol] = incl;
	}
	for (int icol = 1; icol <= abs(nsel); icol++) {
	  int itmp = colsel[icol];
	  if (0 < itmp && itmp < 1000) {
	    exclude[itmp] = !incl;
	  }
	}
	exclude[0] = 0;
	
	// Selection by keyword type.
	if (keysel) {
	  int itmp = keysel;
	  keysel = 0;
	  if (itmp & WCSHDR_IMGHEAD) keysel |= IMGHEAD;
	  if (itmp & WCSHDR_BIMGARR) keysel |= BIMGARR;
	  if (itmp & WCSHDR_PIXLIST) keysel |= PIXLIST;
	}
	if (keysel == 0) {
	  keysel = IMGHEAD | BINTAB;
	}
	
	// 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);


^TFIELDS" = "" "*{INTEGER} {
	  if (ipass == 1) {
	    if (alts.ncol == 0) {
	      sscanf(yytext, "TFIELDS = %d", &(alts.ncol));
	      BEGIN(FLUSH);
	    } else {
	      errmsg = "duplicate or out-of-sequence TFIELDS keyword";
	      BEGIN(ERROR);
	    }
	
	  } else {
	    BEGIN(FLUSH);
	  }
	}

^WCSAXES{ALT}=" "" "*{INTEGER} {
	  if (!(keysel & IMGAXIS)) {
	    // Ignore this key type.
	    BEGIN(DISCARD);
	
	  } else {
	    if (relax & WCSHDR_ALLIMG) {
	      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";
	        keytype = IMGAXIS;
	        BEGIN(COMMENT);
	      }
	
	    } else if (relax & WCSHDR_reject) {
	      errmsg = "image-header keyword WCSAXESa in binary table";
	      BEGIN(ERROR);
	
	    } else {
	      // Pretend we don't recognize it.
	      BEGIN(DISCARD);
	    }
	  }
	}

^WCAX{I1}{ALT}"  = "" "*{INTEGER} |
^WCAX{I2}{ALT}" = "" "*{INTEGER}  |
^WCAX{I3}{ALT}"= "" "*{INTEGER} {
	  keyname = "WCAXna";
	
	  // Note that a blank in the sscanf() format string matches zero or
	  // more of them in the input.
	  sscanf(yytext, "WCAX%d%c = %d", &n, &a, &i);
	
	  if (!(keysel & BIMGARR) || exclude[n]) {
	    // Ignore this key type or column.
	    BEGIN(DISCARD);
	
	  } else if (i < 0) {
	    errmsg = "negative value of WCSAXESa ignored";
	    BEGIN(ERROR);
	
	  } else {
	    valtype = INTEGER;
	    vptr    = 0x0;
	
	    keyname = "WCAXna";
	    keytype = IMGAXIS;
	    BEGIN(COMMENT);
	  }
	}

^WCST{I1}{ALT}"  = "" "*{STRING} |
^WCST{I2}{ALT}" = "" "*{STRING} |
^WCST{I3}{ALT}"= "" "*{STRING} {
	  // Cross-reference supplier.
	  keyname = "WCSTna";
	  errmsg = "cross-references are not implemented";
	  BEGIN(ERROR);
	}

^WCSX{I1}{ALT}"  = "" "*{STRING} |
^WCSX{I2}{ALT}" = "" "*{STRING} |
^WCSX{I3}{ALT}"= "" "*{STRING} {
	  // Cross-reference consumer.
	  keyname = "WCSXna";
	  errmsg = "cross-references are not implemented";
	  BEGIN(ERROR);
	}

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

^{I1}CRP  |
^{I1}CRPX {
	  valtype = FLOAT;
	  vptr    = &(wcstem.crpix);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "jCRPna";
	    BEGIN(iCCCna);
	  } else {
	    keyname = "jCRPXn";
	    BEGIN(iCCCCn);
	  }
	}

^TCRP	|
^TCRPX	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.crpix);
	
	  if (yyleng == 4) {
	    keyname = "TCRPna";
	    BEGIN(TCCCna);
	  } else {
	    keyname = "TCRPXn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I2}PC	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.pc);
	  altlin  = 1;
	
	  sscanf(yytext, "%1d%1d", &i, &j);
	
	  keyname = "ijPCna";
	  BEGIN(ijCCna);
	}

^TP	|
^TPC	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.pc);
	  altlin  = 1;
	
	  if (yyleng == 2) {
	    keyname = "TPn_ka";
	    BEGIN(TCn_ka);
	  } else {
	    keyname = "TPCn_ka";
	    BEGIN(TCCn_ka);
	  }
	}

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

^{I2}CD	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cd);
	  altlin  = 2;
	
	  sscanf(yytext, "%1d%1d", &i, &j);
	
	  keyname = "ijCDna";
	  BEGIN(ijCCna);
	}

^TC	|
^TCD	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cd);
	  altlin  = 2;
	
	  if (yyleng == 2) {
	    keyname = "TCn_ka";
	    BEGIN(TCn_ka);
	  } else {
	    keyname = "TCDn_ka";
	    BEGIN(TCCn_ka);
	  }
	}

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

^{I1}CDE  |
^{I1}CDLT {
	  valtype = FLOAT;
	  vptr    = &(wcstem.cdelt);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCDEna";
	    BEGIN(iCCCna);
	  } else {
	    keyname = "iCDLTn";
	    BEGIN(iCCCCn);
	  }
	}

^TCDE	|
^TCDLT	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cdelt);
	
	  if (yyleng == 4) {
	    keyname = "TCDEna";
	    BEGIN(TCCCna);
	  } else {
	    keyname = "TCDLTn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I1}CROT {
	  valtype = FLOAT;
	  vptr    = &(wcstem.crota);
	  altlin  = 4;
	
	  sscanf(yytext, "%d", &i);
	
	  keyname = "iCROTn";
	  BEGIN(iCROTn);
	}

^TCROT	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.crota);
	  altlin  = 4;
	
	  keyname = "TCROTn";
	  BEGIN(TCROTn);
	}

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

^{I1}CUN  |
^{I1}CUNI {
	  valtype = STRING;
	  vptr    = &(wcstem.cunit);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCUNna";
	    BEGIN(iCCCna);
	  } else {
	    keyname = "iCUNIn";
	    BEGIN(iCCCCn);
	  }
	}

^TCUN	|
^TCUNI	{
	  valtype = STRING;
	  vptr    = &(wcstem.cunit);
	
	  if (yyleng == 4) {
	    keyname = "TCUNna";
	    BEGIN(TCCCna);
	  } else {
	    keyname = "TCUNIn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I1}CTY  |
^{I1}CTYP {
	  valtype = STRING;
	  vptr    = &(wcstem.ctype);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCTYna";
	    BEGIN(iCCCna);
	  } else {
	    keyname = "iCTYPn";
	    BEGIN(iCCCCn);
	  }
	}

^TCTY	|
^TCTYP	{
	  valtype = STRING;
	  vptr    = &(wcstem.ctype);
	
	  if (yyleng == 4) {
	    keyname = "TCTYna";
	    BEGIN(TCCCna);
	  } else {
	    keyname = "TCTYPn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I1}CRV  |
^{I1}CRVL {
	  valtype = FLOAT;
	  vptr    = &(wcstem.crval);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCRVna";
	    BEGIN(iCCCna);
	  } else {
	    keyname = "iCRVLn";
	    BEGIN(iCCCCn);
	  }
	}

^TCRV	|
^TCRVL	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.crval);
	
	  if (yyleng == 4) {
	    keyname = "TCRVna";
	    BEGIN(TCCCna);
	  } else {
	    keyname = "TCRVLn";
	    BEGIN(TCCCCn);
	  }
	}

^LONPOLE |
^LONP	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.lonpole);
	
	  if (yyleng == 7) {
	    keyname = "LONPOLEa";
	    imherit = 0;
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "LONPna";
	    BEGIN(CCCCna);
	  }
	}

^LATPOLE |
^LATP	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.latpole);
	
	  if (yyleng == 7) {
	    keyname = "LATPOLEa";
	    imherit = 0;
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "LATPna";
	    BEGIN(CCCCna);
	  }
	}

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

^RESTWAV |
^RWAV	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.restwav);
	
	  if (yyleng == 7) {
	    keyname = "RESTWAVa";
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "RWAVna";
	    BEGIN(CCCCna);
	  }
	}

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

^{I1}V	|
^{I1}PV	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.pv);
	  ptype   = 'v';
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 2) {
	    keyname = "iVn_ma";
	    BEGIN(iCn_ma);
	  } else {
	    keyname = "iPVn_ma";
	    BEGIN(iCCn_ma);
	  }
	}

^TV	|
^TPV	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.pv);
	  ptype   = 'v';
	
	  if (yyleng == 2) {
	    keyname = "TVn_ma";
	    BEGIN(TCn_ma);
	  } else {
	    keyname = "TPVn_ma";
	    BEGIN(TCCn_ma);
	  }
	}

^PROJP	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.pv);
	  ptype   = 'v';
	
	  keyname = "PROJPm";
	  BEGIN(PROJPm);
	}

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

^{I1}S	|
^{I1}PS	{
	  valtype = STRING;
	  vptr    = &(wcstem.ps);
	  ptype   = 's';
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 2) {
	    keyname = "iSn_ma";
	    BEGIN(iCn_ma);
	  } else {
	    keyname = "iPSn_ma";
	    BEGIN(iCCn_ma);
	  }
	}

^TS	|
^TPS	{
	  valtype = STRING;
	  vptr    = &(wcstem.ps);
	  ptype   = 's';
	
	  if (yyleng == 2) {
	    keyname = "TSn_ma";
	    BEGIN(TCn_ma);
	  } else {
	    keyname = "TPSn_ma";
	    BEGIN(TCCn_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";
	    imherit = 0;
	    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);
	}

^{I1}CNA  |
^{I1}CNAM {
	  valtype = STRING;
	  vptr    = &(wcstem.cname);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCNAna";
	    BEGIN(iCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "iCNAMn";
	    BEGIN(iCCCCn);
	  }
	}

^TCNA	|
^TCNAM	{
	  valtype = STRING;
	  vptr    = &(wcstem.cname);
	
	  if (yyleng == 4) {
	    keyname = "TCNAna";
	    BEGIN(TCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "TCNAMn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I1}CRD |
^{I1}CRDE {
	  valtype = FLOAT;
	  vptr    = &(wcstem.crder);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCRDna";
	    BEGIN(iCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "iCRDEn";
	    BEGIN(iCCCCn);
	  }
	}

^TCRD	|
^TCRDE	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.crder);
	
	  if (yyleng == 4) {
	    keyname = "TCRDna";
	    BEGIN(TCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "TCRDEn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I1}CSY  |
^{I1}CSYE {
	  valtype = FLOAT;
	  vptr    = &(wcstem.csyer);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCSYna";
	    BEGIN(iCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "iCSYEn";
	    BEGIN(iCCCCn);
	  }
	}

^TCSY	|
^TCSYE	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.csyer);
	
	  if (yyleng == 4) {
	    keyname = "TCSYna";
	    BEGIN(TCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "TCSYEn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I1}CZP  |
^{I1}CZPH {
	  valtype = FLOAT;
	  vptr    = &(wcstem.czphs);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCZPna";
	    BEGIN(iCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "iCZPHn";
	    BEGIN(iCCCCn);
	  }
	}

^TCZP	|
^TCZPH	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.czphs);
	
	  if (yyleng == 4) {
	    keyname = "TCZPna";
	    BEGIN(TCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "TCZPHn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I1}CPR  |
^{I1}CPER {
	  valtype = FLOAT;
	  vptr    = &(wcstem.cperi);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCPRna";
	    BEGIN(iCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "iCPERn";
	    BEGIN(iCCCCn);
	  }
	}

^TCPR	|
^TCPER	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cperi);
	
	  if (yyleng == 4) {
	    keyname = "TCPRna";
	    BEGIN(TCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "TCPERn";
	    BEGIN(TCCCCn);
	  }
	}

^WCSNAME |
^WCSN	 |
^TWCS	{
	  valtype = STRING;
	  vptr    = wcstem.wcsname;
	
	  if (yyleng == 7) {
	    keyname = "WCSNAMEa";
	    imherit = 0;
	    BEGIN(CCCCCCCa);
	
	  } else {
	    if (*yytext == 'W') {
	      keyname = "WCSNna";
	    } else {
	      keyname = "TWCSna";
	    }
	    BEGIN(CCCCna);
	  }
	}

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

^TREFPOS" " |
^TRPOS  {
	  valtype = STRING;
	  vptr    = wcstem.trefpos;
	
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "TREFPOS";
	    BEGIN(CCCCCCCC);
	  } else {
	    keyname = "TRPOSn";
	    BEGIN(CCCCCn);
	  }
	}

^TREFDIR" " |
^TRDIR  {
	  valtype = STRING;
	  vptr    = wcstem.trefdir;
	
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "TREFDIR";
	    BEGIN(CCCCCCCC);
	  } else {
	    keyname = "TRDIRn";
	    BEGIN(CCCCCn);
	  }
	}

^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 = wcsbth_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 = wcsbth_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 = wcsbth_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";
	  imherit = 0;
	  BEGIN(CCCCCCCC);
	}

^DOBS{I1}"   " |
^DOBS{I2}"  "  |
^DOBS{I3}" " {
	  valtype = STRING;
	  vptr    = wcstem.dateobs;
	
	  if (relax & WCSHDR_DOBSn) {
	    yyless(4);
	
	    keyname = "DOBSn";
	    BEGIN(CCCCn);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "DOBSn keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

^DATE-AVG |
^DAVG   {
	  valtype = STRING;
	  vptr    = wcstem.dateavg;
	
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "DATE-AVG";
	    BEGIN(CCCCCCCC);
	  } else {
	    keyname = "DAVGn";
	    BEGIN(CCCCn);
	  }
	}

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

^MJD-OBS" " |
^MJDOB	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdobs);
	
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "MJD-OBS";
	    imherit = 0;
	    BEGIN(CCCCCCCC);
	  } else {
	    keyname = "MJDOBn";
	    BEGIN(CCCCCn);
	  }
	}

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

^MJD-AVG" " |
^MJDA	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdavg);
	
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "MJD-AVG";
	    BEGIN(CCCCCCCC);
	  } else {
	    keyname = "MJDAn";
	    BEGIN(CCCCn);
	  }
	}

^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 = wcsbth_timepixr;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMEPIXR";
	  BEGIN(CCCCCCCC);
	}

^OBSGEO-X |
^OBSGX	{
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo;
	
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "OBSGEO-X";
	    BEGIN(CCCCCCCC);
	  } else {
	    keyname = "OBSGXn";
	    BEGIN(CCCCCn);
	  }
	}

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

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

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

^OBSGL{I1}"  " |
^OBSGL{I2}" "  |
^OBSGL{I3} {
	  valtype = STRING;
	  vptr    = wcstem.obsgeo + 3;
	
	  if (relax & WCSHDR_OBSGLBHn) {
	    yyless(5);
	
	    keyname = "OBSGLn";
	    BEGIN(CCCCCn);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "OBSGLn keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

^OBSGB{I1}"  " |
^OBSGB{I2}" "  |
^OBSGB{I3} {
	  valtype = STRING;
	  vptr    = wcstem.obsgeo + 3;
	
	  if (relax & WCSHDR_OBSGLBHn) {
	    yyless(5);
	
	    keyname = "OBSGBn";
	    BEGIN(CCCCCn);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "OBSGBn keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

^OBSGH{I1}"  " |
^OBSGH{I2}" "  |
^OBSGH{I3} {
	  valtype = STRING;
	  vptr    = wcstem.obsgeo + 3;
	
	  if (relax & WCSHDR_OBSGLBHn) {
	    yyless(5);
	
	    keyname = "OBSGHn";
	    BEGIN(CCCCCn);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "OBSGHn keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

^RADESYS |
^RADE	{
	  valtype = STRING;
	  vptr    = wcstem.radesys;
	
	  if (yyleng == 7) {
	    keyname = "RADESYSa";
	    imherit = 0;
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "RADEna";
	    BEGIN(CCCCna);
	  }
	}

^RADECSYS {
	  if (relax & WCSHDR_RADECSYS) {
	    valtype = STRING;
	    vptr    = wcstem.radesys;
	
	    unput(' ');
	
	    keyname = "RADECSYS";
	    imherit = 0;
	    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 = wcsbth_epoch;
	
	    unput(a);
	
	    keyname = "EPOCH";
	    imherit = 0;
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "EPOCH keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^EQUINOX |
^EQUI	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.equinox);
	
	  if (yyleng == 7) {
	    keyname = "EQUINOXa";
	    imherit = 0;
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "EQUIna";
	    BEGIN(CCCCna);
	  }
	}

^SPECSYS |
^SPEC	{
	  valtype = STRING;
	  vptr    = wcstem.specsys;
	
	  if (yyleng == 7) {
	    keyname = "SPECSYSa";
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "SPECna";
	    BEGIN(CCCCna);
	  }
	}

^SSYSOBS |
^SOBS	{
	  valtype = STRING;
	  vptr    = wcstem.ssysobs;
	
	  if (yyleng == 7) {
	    keyname = "SSYSOBSa";
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "SOBSna";
	    BEGIN(CCCCna);
	  }
	}

^VELOSYS |
^VSYS	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.velosys);
	
	  if (yyleng == 7) {
	    keyname = "VELOSYSa";
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "VSYSna";
	    BEGIN(CCCCna);
	  }
	}

^VSOURCE{ALT} {
	  if (relax & WCSHDR_VSOURCE) {
	    valtype = FLOAT;
	    vptr    = &(wcstem.zsource);
	    special = wcsbth_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);
	  }
	}

^VSOU{I1}{ALT}"  " |
^VSOU{I2}{ALT}" "  |
^VSOU{I3}{ALT} {
	  if (relax & WCSHDR_VSOURCE) {
	    valtype = FLOAT;
	    vptr    = &(wcstem.zsource);
	    special = wcsbth_vsource;
	
	    yyless(4);
	    keyname = "VSOUna";
	    BEGIN(CCCCna);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VSOUna keyword is deprecated, use ZSOUna";
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

^ZSOURCE |
^ZSOU	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.zsource);
	
	  if (yyleng == 7) {
	    keyname = "ZSOURCEa";
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "ZSOUna";
	    BEGIN(CCCCna);
	  }
	}

^SSYSSRC |
^SSRC	{
	  valtype = STRING;
	  vptr    = wcstem.ssyssrc;
	
	  if (yyleng == 7) {
	    keyname = "SSYSSRCa";
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "SSRCna";
	    BEGIN(CCCCna);
	  }
	}

^VELANGL |
^VANG	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.velangl);
	
	  if (yyleng == 7) {
	    keyname = "VELANGLa";
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "VANGna";
	    BEGIN(CCCCna);
	  }
	}

^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);
	}

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

^.	{
	  BEGIN(DISCARD);
	}

<CCCCCia>{I1}{ALT}" " |
<CCCCCia>{I2}{ALT} {
	  if (relax & WCSHDR_ALLIMG) {
	    sscanf(yytext, "%d%c", &i, &a);
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CCCCCia>0{I1}{ALT} |
<CCCCCia>00{I1} {
	  if (relax & WCSHDR_ALLIMG) {
	    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);
	    }
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "invalid image-header keyword %s in binary table", keyname);
	    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.
	  if (relax & WCSHDR_ALLIMG) {
	    errmsg = "axis number must exceed 0";
	    BEGIN(ERROR);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "invalid image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    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 {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<iCCCCn>{I1}"  " |
<iCCCCn>{I2}" "  |
<iCCCCn>{I3}     |
<TCCCCn>{I1}"  " |
<TCCCCn>{I2}" "  |
<TCCCCn>{I3} {
	  if (vptr) {
	    WCSBTH_PUTBACK;
	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80, "%s keyword is non-standard", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

<iCCCCn>{I1}[A-Z]" " |
<iCCCCn>{I2}[A-Z]    |
<TCCCCn>{I1}[A-Z]" " |
<TCCCCn>{I2}[A-Z] {
	  if (vptr && (relax & WCSHDR_LONGKEY)) {
	    WCSBTH_PUTBACK;
	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    if (!vptr) {
	      snprintf(errmsg, 80, "%s keyword is non-standard", keyname);
	    } else {
	      snprintf(errmsg, 80,
	        "%s keyword may not have an alternate version code", keyname);
	    }
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<iCCCCn>. |
<TCCCCn>. {
	  BEGIN(DISCARD);
	}

<iCCCna>{I1}{ALT}"  " |
<iCCCna>{I2}{ALT}" "  |
<iCCCna>{I3}{ALT}     |
<TCCCna>{I1}{ALT}"  " |
<TCCCna>{I2}{ALT}" "  |
<TCCCna>{I3}{ALT} {
	  sscanf(yytext, "%d%c", &n, &a);
	  if (YY_START == TCCCna) i = wcsbth_colax(*wcs, &alts, n, a);
	  keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
	  BEGIN(VALUE);
	}

<iCCCna>. |
<TCCCna>. {
	  BEGIN(DISCARD);
	}

<CCi_ja>{I1}_{I1}{ALT}"  " |
<CCi_ja>{I1}_{I2}{ALT}" " |
<CCi_ja>{I2}_{I1}{ALT}" " |
<CCi_ja>{I2}_{I2}{ALT} {
	  if (relax & WCSHDR_ALLIMG) {
	    sscanf(yytext, "%d_%d%c", &i, &j, &a);
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<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 (relax & WCSHDR_ALLIMG) {
	    if (((altlin == 1) && (relax & WCSHDR_PC0i_0ja)) ||
	        ((altlin == 2) && (relax & WCSHDR_CD0i_0ja))) {
	      sscanf(yytext, "%d_%d%c", &i, &j, &a);
	      keytype = IMGAXIS;
	      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);
	    }
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "invalid image-header keyword %s in binary table", keyname);
	    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.
	  if (relax & WCSHDR_ALLIMG) {
	    errmsg = "axis number must exceed 0";
	    BEGIN(ERROR);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "invalid image-header keyword %s in binary table", keyname);
	    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} {
	  if (relax & WCSHDR_ALLIMG) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "%s keyword must use an underscore, not a dash", keyname);
	    BEGIN(ERROR);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "invalid image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CCi_ja>{Z1}{6} {
	  // This covers the defunct forms CD00i00j and PC00i00j.
	  if (relax & WCSHDR_ALLIMG) {
	    if (((altlin == 1) && (relax & WCSHDR_PC00i00j)) ||
	        ((altlin == 2) && (relax & WCSHDR_CD00i00j))) {
	      sscanf(yytext, "%3d%3d", &i, &j);
	      a = ' ';
	      keytype = IMGAXIS;
	      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);
	    }
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "deprecated image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CCi_ja>. {
	  BEGIN(DISCARD);
	}

<ijCCna>{I1}{ALT}"  " |
<ijCCna>{I2}{ALT}" "  |
<ijCCna>{I3}{ALT} {
	  sscanf(yytext, "%d%c", &n, &a);
	  keytype = BIMGARR;
	  BEGIN(VALUE);
	}

<TCCn_ka>{I1}_{I1}{ALT}" " |
<TCCn_ka>{I1}_{I2}{ALT} |
<TCCn_ka>{I2}_{I1}{ALT} |
<TCCn_ka>{I1}_{I3} |
<TCCn_ka>{I2}_{I2} |
<TCCn_ka>{I3}_{I1} {
	  if (relax & WCSHDR_LONGKEY) {
	    WCSBTH_PUTBACK;
	    BEGIN(TCn_ka);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80, "%s keyword is non-standard", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<TCCn_ka>. {
	  BEGIN(DISCARD);
	}

<TCn_ka>{I1}_{I1}{ALT}"  " |
<TCn_ka>{I1}_{I2}{ALT}" " |
<TCn_ka>{I2}_{I1}{ALT}" " |
<TCn_ka>{I1}_{I3}{ALT} |
<TCn_ka>{I2}_{I2}{ALT} |
<TCn_ka>{I3}_{I1}{ALT} {
	  sscanf(yytext, "%d_%d%c", &n, &k, &a);
	  i = wcsbth_colax(*wcs, &alts, n, a);
	  j = wcsbth_colax(*wcs, &alts, k, a);
	  keytype = PIXLIST;
	  BEGIN(VALUE);
	}

<TCn_ka>{I1}_{I4} |
<TCn_ka>{I2}_{I3} |
<TCn_ka>{I3}_{I2} |
<TCn_ka>{I4}_{I1} {
	  sscanf(yytext, "%d_%d", &n, &k);
	  a = ' ';
	  i = wcsbth_colax(*wcs, &alts, n, a);
	  j = wcsbth_colax(*wcs, &alts, k, a);
	  keytype = PIXLIST;
	  BEGIN(VALUE);
	}

<TCn_ka>. {
	  BEGIN(DISCARD);
	}

<CROTAi>{Z1}{ALT}" " |
<CROTAi>{Z2}{ALT} |
<CROTAi>{Z3} {
	  if (relax & WCSHDR_ALLIMG) {
	    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);
	    }
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "deprecated image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<CROTAi>. {
	  if (relax & WCSHDR_ALLIMG) {
	    yyless(0);
	    BEGIN(CCCCCia);
	  } else {
	    // Let it go.
	    BEGIN(DISCARD);
	  }
	}

<iCROTn>{I1}"  " |
<iCROTn>{I2}" "  |
<iCROTn>{I3}     |
<TCROTn>{I1}"  " |
<TCROTn>{I2}" "  |
<TCROTn>{I3} {
	  WCSBTH_PUTBACK;
	  BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
	}

<iCROTn>{I1}[A-Z]" " |
<iCROTn>{I2}[A-Z]    |
<TCROTn>{I1}[A-Z]" " |
<TCROTn>{I2}[A-Z] {
	  if (relax & WCSHDR_CROTAia) {
	    WCSBTH_PUTBACK;
	    BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "%s keyword may not have an alternate version code", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<iCROTn>. |
<TCROTn>. {
	  BEGIN(DISCARD);
	}

<CCCCCCCa>{ALT} |
<CCCCCCCC>. {
	  // Image-header keyword.
	  if (imherit || (relax & (WCSHDR_AUXIMG | WCSHDR_ALLIMG))) {
	    if (YY_START == CCCCCCCa) {
	      sscanf(yytext, "%c", &a);
	    } else {
	      a = 0;
	      unput(yytext[0]);
	    }
	    keytype = IMGAUX;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<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);
	  }
	}

<CCCCna>{I1}{ALT}"  " |
<CCCCna>{I2}{ALT}" "  |
<CCCCna>{I3}{ALT}     |
<CCCCCna>{I1}{ALT}" " |
<CCCCCna>{I2}{ALT} {
	  sscanf(yytext, "%d%c", &n, &a);
	  keytype = BINTAB;
	  BEGIN(VALUE);
	}

<CCCCCna>{I3} {
	  sscanf(yytext, "%d", &n);
	  a = ' ';
	  keytype = BINTAB;
	  BEGIN(VALUE);
	}

<CCCCna>. |
<CCCCCna>. {
	  BEGIN(DISCARD);
	}

<CCCCn>{I1}"   " |
<CCCCn>{I2}"  "  |
<CCCCn>{I3}" "   |
<CCCCn>{I4}      |
<CCCCCn>{I1}"  " |
<CCCCCn>{I2}" "  |
<CCCCCn>{I3} {
	  sscanf(yytext, "%d", &n);
	  a = 0;
	  keytype = BINTAB;
	  BEGIN(VALUE);
	}

<CCCCn>. |
<CCCCCn>. {
	  BEGIN(DISCARD);
	}

<CCi_ma>{I1}_{Z1}{ALT}"  " |
<CCi_ma>{I1}_{I2}{ALT}" " |
<CCi_ma>{I2}_{Z1}{ALT}" " |
<CCi_ma>{I2}_{I2}{ALT} {
	  // Image-header keyword.
	  if (relax & WCSHDR_ALLIMG) {
	    sscanf(yytext, "%d_%d%c", &i, &m, &a);
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<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 (relax & WCSHDR_ALLIMG) {
	    if (((valtype == FLOAT)  && (relax & WCSHDR_PV0i_0ma)) ||
	        ((valtype == STRING) && (relax & WCSHDR_PS0i_0ma))) {
	      sscanf(yytext, "%d_%d%c", &i, &m, &a);
	      keytype = IMGAXIS;
	      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);
	    }
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "invalid image-header keyword %s in binary table", keyname);
	    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} {
	  if (relax & WCSHDR_ALLIMG) {
	    // Anything that has fallen through to this point must contain
	    // an invalid parameter.
	    errmsg = "axis number must exceed 0";
	    BEGIN(ERROR);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80,
	      "invalid image-header keyword %s in binary table", keyname);
	    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} {
	  errmsg = errtxt;
	  snprintf(errmsg, 80,
	    "%s keyword must use an underscore, not a dash", keyname);
	  BEGIN(ERROR);
	}

<CCi_ma>. {
	  BEGIN(DISCARD);
	}

<iCCn_ma>{I1}_{Z1}{ALT}" " |
<iCCn_ma>{I1}_{I2}{ALT}    |
<iCCn_ma>{I1}_{I3}         |
<iCCn_ma>{I2}_{Z1}{ALT}    |
<iCCn_ma>{I2}_{I2}         |
<iCCn_ma>{I3}_{Z1}         |
<TCCn_ma>{I1}_{Z1}{ALT}" " |
<TCCn_ma>{I1}_{I2}{ALT}    |
<TCCn_ma>{I1}_{I3}         |
<TCCn_ma>{I2}_{Z1}{ALT}    |
<TCCn_ma>{I2}_{I2}         |
<TCCn_ma>{I3}_{Z1} {
	  if (relax & WCSHDR_LONGKEY) {
	    WCSBTH_PUTBACK;
	    BEGIN((YY_START == iCCn_ma) ? iCn_ma : TCn_ma);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    snprintf(errmsg, 80, "the %s keyword is non-standard", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

<iCCn_ma>. |
<TCCn_ma>. {
	  BEGIN(DISCARD);
	}

<iCn_ma>{I1}_{Z1}{ALT}"  " |
<iCn_ma>{I1}_{I2}{ALT}" "  |
<iCn_ma>{I1}_{I3}{ALT}     |
<iCn_ma>{I2}_{Z1}{ALT}" "  |
<iCn_ma>{I2}_{I2}{ALT}     |
<iCn_ma>{I3}_{Z1}{ALT}     |
<TCn_ma>{I1}_{Z1}{ALT}"  " |
<TCn_ma>{I1}_{I2}{ALT}" "  |
<TCn_ma>{I1}_{I3}{ALT}     |
<TCn_ma>{I2}_{Z1}{ALT}" "  |
<TCn_ma>{I2}_{I2}{ALT}     |
<TCn_ma>{I3}_{Z1}{ALT} {
	  sscanf(yytext, "%d_%d%c", &n, &m, &a);
	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
	  BEGIN(VALUE);
	}

<iCn_ma>{I1}_{I4} |
<iCn_ma>{I2}_{I3} |
<iCn_ma>{I3}_{I2} |
<iCn_ma>{I4}_{Z1} |
<TCn_ma>{I1}_{I4} |
<TCn_ma>{I2}_{I3} |
<TCn_ma>{I3}_{I2} |
<TCn_ma>{I4}_{Z1} {
	  // Invalid combinations will be flagged by <VALUE>.
	  sscanf(yytext, "%d_%d", &n, &m);
	  a = ' ';
	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
	  BEGIN(VALUE);
	}

<iCn_ma>. |
<TCn_ma>. {
	  BEGIN(DISCARD);
	}

<PROJPm>{Z1}"  " {
	  if (relax & WCSHDR_PROJPn) {
	    sscanf(yytext, "%d", &m);
	    i = 0;
	    a = ' ';
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the PROJPn keyword is deprecated, use PVi_ma";
	    BEGIN(ERROR);
	
	  } else {
	    // Pretend we don't recognize it.
	    BEGIN(DISCARD);
	  }
	}

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

<PROJPm>. {
	  BEGIN(DISCARD);
	}

<VALUE>=" "+ {
	  // Do checks on i, j, m, n, k.
	  if (!(keytype & keysel)) {
	    // Selection by keyword type.
	    BEGIN(DISCARD);
	
	  } else if (exclude[n] || exclude[k]) {
	    // One or other column is not selected.
	    if (k && (exclude[n] != exclude[k])) {
	      // For keywords such as TCn_ka, both columns must be excluded.
	      // User error, so return immediately.
	      return WCSHDRERR_BAD_COLUMN;
	
	    } else {
	      BEGIN(DISCARD);
	    }
	
	  } else if (i > 99 || j > 99 || m > 99 || n > 999 || k > 999) {
	    if (relax & WCSHDR_reject) {
	      errmsg = errtxt;
	      if (i > 99 || j > 99) {
	        snprintf(errmsg, 80, "axis number exceeds 99");
	      } else if (m > 99) {
	        snprintf(errmsg, 80, "parameter number exceeds 99");
	      } else if (n > 999 || k > 999) {
	        snprintf(errmsg, 80, "column number exceeds 999");
	      }
	      BEGIN(ERROR);
	
	    } else {
	      // Pretend we don't recognize it.
	      BEGIN(DISCARD);
	    }
	
	  } else if (ipass == 2 && npass == 3 && (keytype & BINTAB)) {
	    // Skip keyvalues that won't be inherited.
	    BEGIN(FLUSH);
	
	  } else {
	    if (ipass == 3 && (keytype & IMGHEAD)) {
	      // IMGHEAD keytypes are always dealt with on the second pass.
	      // However, they must be re-parsed in order to report errors.
	      vptr = 0x0;
	    }
	
	    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 {
	      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);
	}

<COMMENT>{INLINE}$ {
	  if (ipass == 1) {
	    // Do first-pass bookkeeping.
	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
	    BEGIN(FLUSH);
	
	  } else if (*wcs) {
	    // Store the value now that the keyrecord has been validated.
	    alts.icol = 0;
	    alts.ialt = 0;
	
	    // Update each coordinate representation.
	    int gotone = 0;
	    struct wcsprm *wcsp;
	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
	      gotone = 1;
	
	      if (vptr) {
	        void *wptr;
	        if (auxprm) {
	          // Additional auxiliary parameter.
	          auxp = wcsp->aux;
	          ptrdiff_t voff = (char *)vptr - (char *)(&auxtem);
	          wptr = (void *)((char *)auxp + voff);
	        } else {
	          // A parameter that lives directly in wcsprm.
	          ptrdiff_t voff = (char *)vptr - (char *)(&wcstem);
	          wptr = (void *)((char *)wcsp + voff);
	        }
	
	        if (valtype == INTEGER) {
	          *((int *)wptr) = inttmp;
	
	        } else if (valtype == FLOAT) {
	          // Apply keyword parameterization.
	          if (ptype == 'v') {
	            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 the 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 (ptype == 's') {
	            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);
	        }
	      }
	    }
	
	    if (ipass == npass) {
	      if (gotone) {
	        nvalid++;
	        if (ctrl == 4) {
	          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);
	    }
	
	  } 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) {
	      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;
	  auxprm = 0;
	
	  // Throw away the rest of the line and reset for the next one.
	  i = j = 0;
	  n = k = 0;
	  m = 0;
	  a = ' ';
	
	  keyrec += 80;
	
	  keytype =  0;
	  valtype = -1;
	  vptr    = 0x0;
	  keep    = 0x0;
	
	  altlin  = 0;
	  ptype   = ' ';
	  chekval = 0x0;
	  special = 0x0;
	
	  BEGIN(INITIAL);
	}

<<EOF>>	 {
	  // End-of-input.
	  if (ipass == 1) {
	    int status;
	    if ((status = wcsbth_init1(&alts, naux, 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);
	      }
	    }
	
	    if (alts.imgherit) npass = 3;
	  }
	
	  if (ipass++ < npass) {
	    yyextra->hdr = header;
	    yyextra->nkeyrec = nkeyrec;
	    keyrec = header;
	    *nreject = 0;
	
	    imherit = 1;
	
	    i = j = 0;
	    k = n = 0;
	    m = 0;
	    a = ' ';
	
	    keytype =  0;
	    valtype = -1;
	    vptr    = 0x0;
	
	    altlin = 0;
	    ptype  = ' ';
	    chekval = 0x0;
	    special = 0x0;
	
	    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");
	    }
	
	    return wcsbth_final(&alts, nwcs, wcs);
	  }
	}

%%

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

int wcsbth(
  char *header,
  int nkeyrec,
  int relax,
  int ctrl,
  int keysel,
  int *colsel,
  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 wcsbth_extra extra;
  yyscan_t yyscanner;
  yylex_init_extra(&extra, &yyscanner);
  int status = wcsbth_scanner(header, nkeyrec, relax, ctrl, keysel, colsel,
                              nreject, nwcs, wcs, yyscanner);
  yylex_destroy(yyscanner);

  return status;
}

/*----------------------------------------------------------------------------
* Perform first-pass tasks:
*
* 1) Count the number of coordinate axes in each of the 27 possible alternate
*    image-header coordinate representations.  Also count the number of PVi_ma
*    and PSi_ma keywords in each representation.
*
* 2) Determine the number of binary table columns that have an image array
*    with a coordinate representation (up to 999), and count the number of
*    coordinate axes in each of the 27 possible alternates.  Also count the
*    number of iVn_ma and iSn_ma keywords in each representation.
*
* 3) Determine the number of alternate pixel list coordinate representations
*    (up to 27) and the table columns associated with each.  Also count the
*    number of TVn_ma and TSn_ma keywords in each representation.
*
* In the first pass alts->arridx[icol][27] is used to determine the number of
* axes in each of 27 possible image-header coordinate descriptions (icol == 0)
* and each of the 27 possible coordinate representations for an image array in
* each column.
*
* The elements of alts->pixlist[icol] are used as bit arrays to flag which of
* the 27 possible pixel list coordinate representations are associated with
* each table column.
*---------------------------------------------------------------------------*/

int wcsbth_pass1(
  int keytype,
  int i,
  int j,
  int n,
  int k,
  char a,
  char ptype,
  struct wcsbth_alts *alts)

{
  if (a == 0) {
    // Keywords such as DATE-OBS go along for the ride.
    return 0;
  }

  int ncol = alts->ncol;

  // Do we need to allocate memory for alts?
  if (alts->arridx == 0x0) {
    if (ncol == 0) {
      // Can only happen if TFIELDS is missing or out-of-sequence.  If n and
      // k are both zero then we may be processing an image header so leave
      // ncol alone - the array will be realloc'd later if required.
      if (n || k) {
        // The header is mangled, assume the worst.
        ncol = 999;
      }
    }

    if (!(alts->arridx  =  calloc((1 + ncol)*27, sizeof(short int))) ||
        !(alts->npv     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
        !(alts->nps     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
        !(alts->pixlist =  calloc((1 + ncol),    sizeof(unsigned int)))) {
      if (alts->arridx)  free(alts->arridx);
      if (alts->npv)     free(alts->npv);
      if (alts->nps)     free(alts->nps);
      if (alts->pixlist) free(alts->pixlist);
      return WCSHDRERR_MEMORY;
    }

    alts->ncol = ncol;

  } else if (n > ncol || k > ncol) {
    // Can only happen if TFIELDS or the WCS keyword is wrong; carry on.
    ncol = 999;
    if (!(alts->arridx  = realloc(alts->arridx,
                                    27*(1 + ncol)*sizeof(short int))) ||
        !(alts->npv     = realloc(alts->npv,
                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
        !(alts->nps     = realloc(alts->nps,
                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
        !(alts->pixlist = realloc(alts->pixlist,
                                       (1 + ncol)*sizeof(unsigned int)))) {
      if (alts->arridx)  free(alts->arridx);
      if (alts->npv)     free(alts->npv);
      if (alts->nps)     free(alts->nps);
      if (alts->pixlist) free(alts->pixlist);
      return WCSHDRERR_MEMORY;
    }

    // Since realloc() doesn't initialize the extra memory.
    for (int icol = (1 + alts->ncol); icol < (1 + ncol); icol++) {
      for (int ialt = 0; ialt < 27; ialt++) {
        alts->arridx[icol][ialt] = 0;
        alts->npv[icol][ialt] = 0;
        alts->nps[icol][ialt] = 0;
        alts->pixlist[icol]   = 0;
      }
    }

    alts->ncol = ncol;
  }

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

  // A BINTAB keytype such as LONPna, in conjunction with an IMGAXIS keytype
  // causes a table column to be recognized as an image array.
  if (keytype & IMGHEAD || keytype & BIMGARR) {
    // n == 0 is expected for IMGHEAD keywords.
    if (i == 0 && j == 0) {
      if (alts->arridx[n][ialt] == 0) {
        // Flag that an auxiliary keyword was seen.
        alts->arridx[n][ialt] = -1;
      }

    } else {
      // Record the maximum axis number found.
      if (alts->arridx[n][ialt] < i) {
        alts->arridx[n][ialt] = i;
      }

      if (alts->arridx[n][ialt] < j) {
        alts->arridx[n][ialt] = j;
      }
    }

    if (ptype == 'v') {
      alts->npv[n][ialt]++;
    } else if (ptype == 's') {
      alts->nps[n][ialt]++;
    }
  }

  // BINTAB keytypes, which apply both to pixel lists as well as binary table
  // image arrays, never contribute to recognizing a table column as a pixel
  // list axis.  A PIXLIST keytype is required for that.
  if (keytype == PIXLIST) {
    int mask = 1 << ialt;

    // n > 0 for PIXLIST keytypes.
    alts->pixlist[n] |= mask;
    if (k) alts->pixlist[k] |= mask;

    // Used as a flag over all columns.
    alts->pixlist[0] |= mask;

    if (ptype == 'v') {
      alts->pixnpv[ialt]++;
    } else if (ptype == 's') {
      alts->pixnps[ialt]++;
    }
  }

  return 0;
}


/*----------------------------------------------------------------------------
* Perform initializations at the end of the first pass:
*
* 1) Determine the required number of wcsprm structs, allocate memory for
*    an array of them and initialize each one.
*---------------------------------------------------------------------------*/

int wcsbth_init1(
  struct wcsbth_alts *alts,
  int naux,
  int *nwcs,
  struct wcsprm **wcs)

{
  int status = 0;

  if (alts->arridx == 0x0) {
    *nwcs = 0;
    return 0;
  }

  // Determine the number of axes in each pixel list representation.
  int ialt, mask, ncol = alts->ncol;
  for (ialt = 0, mask = 1; ialt < 27; ialt++, mask <<= 1) {
    alts->pixidx[ialt] = 0;

    if (alts->pixlist[0] | mask) {
      for (int icol = 1; icol <= ncol; icol++) {
        if (alts->pixlist[icol] & mask) {
          alts->pixidx[ialt]++;
        }
      }
    }
  }

  // Find the total number of coordinate representations.
  *nwcs = 0;
  alts->imgherit = 0;
  int inherit[27];
  for (int ialt = 0; ialt < 27; ialt++) {
    inherit[ialt] = 0;

    for (int icol = 1; icol <= ncol; icol++) {
      if (alts->arridx[icol][ialt] < 0) {
        // No BIMGARR keytype but there's at least one BINTAB.
        if (alts->arridx[0][ialt] > 0) {
          // There is an IMGAXIS keytype that we will inherit, so count this
          // representation.
          alts->arridx[icol][ialt] = alts->arridx[0][ialt];
        } else {
          alts->arridx[icol][ialt] = 0;
        }
      }

      if (alts->arridx[icol][ialt]) {
        if (alts->arridx[0][ialt]) {
          // All IMGHEAD keywords are inherited for this ialt.
          inherit[ialt] = 1;

          if (alts->arridx[icol][ialt] < alts->arridx[0][ialt]) {
            // The extra axes are also inherited.
            alts->arridx[icol][ialt] = alts->arridx[0][ialt];
          }
        }

        (*nwcs)++;
      }
    }

    // Count every "a" found in any IMGHEAD keyword...
    if (alts->arridx[0][ialt]) {
      if (inherit[ialt]) {
        // ...but not if the IMGHEAD keywords will be inherited.
        alts->arridx[0][ialt] = 0;
        alts->imgherit = 1;
      } else if (alts->arridx[0][ialt] > 0) {
        (*nwcs)++;
      }
    }

    // We need a struct for every "a" found in a PIXLIST keyword.
    if (alts->pixidx[ialt]) {
      (*nwcs)++;
    }
  }


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

    // Initialize each wcsprm struct.
    struct wcsprm *wcsp = *wcs;
    *nwcs = 0;
    for (int icol = 0; icol <= ncol; icol++) {
      for (int ialt = 0; ialt < 27; ialt++) {
        if (alts->arridx[icol][ialt] > 0) {
          // Image-header representations that are not for inheritance
          // (icol == 0) or binary table image array representations.
          wcsp->flag = -1;
          int npvmax = alts->npv[icol][ialt];
          int npsmax = alts->nps[icol][ialt];
          if ((status = wcsinit(1, (int)(alts->arridx[icol][ialt]), wcsp,
                                npvmax, npsmax, -1))) {
            wcsvfree(nwcs, wcs);
            break;
          }

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

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

          // Record the table column number.
          wcsp->colnum = icol;

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

          wcsp++;

        } else {
          // Signal that this column has no WCS for this "a".
          alts->arridx[icol][ialt] = -1;
        }
      }
    }

    for (int ialt = 0; ialt < 27; ialt++) {
      if (alts->pixidx[ialt]) {
        // Pixel lists representations.
        wcsp->flag = -1;
        int npvmax = alts->pixnpv[ialt];
        int npsmax = alts->pixnps[ialt];
        if ((status = wcsinit(1, (int)(alts->pixidx[ialt]), wcsp, npvmax,
                              npsmax, -1))) {
          wcsvfree(nwcs, wcs);
          break;
        }

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

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

        // Record the pixel list column numbers.
        int icol, ix, mask = (1 << ialt);
        for (icol = 1, ix = 0; icol <= ncol; icol++) {
          if (alts->pixlist[icol] & mask) {
            wcsp->colax[ix++] = icol;
          }
        }

        // alts->pixidx[] indexes the array of wcsprm structs.
        alts->pixidx[ialt] = (*nwcs)++;

        wcsp++;

      } else {
        // Signal that this column is not a pixel list axis for this "a".
        alts->pixidx[ialt] = -1;
      }
    }
  }

  return status;
}


/*----------------------------------------------------------------------------
* Return a pointer to the next wcsprm struct for a particular column number
* and alternate.
*---------------------------------------------------------------------------*/

struct wcsprm *wcsbth_idx(
  struct wcsprm *wcs,
  struct wcsbth_alts *alts,
  int  keytype,
  int  n,
  char a)

{
  const char as[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";

  if (!wcs) return 0x0;

  int iwcs = -1;
  for (; iwcs < 0 && alts->ialt < 27; alts->ialt++) {
    // Note that a == 0 applies to every alternate, otherwise this
    // loop simply determines the appropriate value of alts->ialt.
    if (a && a != as[alts->ialt]) continue;

    if (keytype & (IMGHEAD | BIMGARR)) {
      for (; iwcs < 0 && alts->icol <= alts->ncol; alts->icol++) {
        // Image header keywords, n == 0, apply to all columns, otherwise this
        // loop simply determines the appropriate value of alts->icol.
        if (n && n != alts->icol) continue;
        iwcs = alts->arridx[alts->icol][alts->ialt];
      }

      // Break out of the loop to stop alts->ialt from being incremented.
      if (iwcs >= 0) break;

      // Start from scratch for the next alts->ialt.
      alts->icol = 0;
    }

    if (keytype & (IMGAUX | PIXLIST)) {
      iwcs = alts->pixidx[alts->ialt];
    }
  }

  return (iwcs >= 0) ? (wcs + iwcs) : 0x0;
}


/*----------------------------------------------------------------------------
* Return the axis number associated with the specified column number in a
* particular pixel list coordinate representation.
*---------------------------------------------------------------------------*/

int wcsbth_colax(
  struct wcsprm *wcs,
  struct wcsbth_alts *alts,
  int n,
  char a)

{
  if (!wcs) return 0;

  struct wcsprm *wcsp = wcs;
  if (a != ' ') {
    wcsp += alts->pixidx[a-'A'+1];
  }

  for (int ix = 0; ix < wcsp->naxis; ix++) {
    if (wcsp->colax[ix] == n) {
      return ++ix;
    }
  }

  return 0;
}


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

int wcsbth_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 wcsbth_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 wcsbth_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 wcsbth_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 wcsbth_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 wcsbth_timepixr(double timepixr)

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


/*----------------------------------------------------------------------------
* Tie up loose ends.
*---------------------------------------------------------------------------*/

int wcsbth_final(
  struct wcsbth_alts *alts,
  int *nwcs,
  struct wcsprm **wcs)

{
  if (alts->arridx)  free(alts->arridx);
  if (alts->npv)     free(alts->npv);
  if (alts->nps)     free(alts->nps);
  if (alts->pixlist) free(alts->pixlist);

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

  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: wcsbth.l,v 8.5.1.2 2026/03/29 13:36:16 mcalabre Exp mcalabre $
d178 1
a178 1
  sprintf(strtmp, "%s ", yytext); \
d1986 1
a1986 1
	    sprintf(errmsg,
d2012 1
a2012 1
	    sprintf(errmsg,
d2033 1
a2033 1
	    sprintf(errmsg,
d2047 1
a2047 1
	    sprintf(errmsg, "keyword looks very much like %s but isn't",
d2069 1
a2069 1
	    sprintf(errmsg, "%s keyword is non-standard", keyname);
d2088 1
a2088 1
	      sprintf(errmsg, "%s keyword is non-standard", keyname);
d2090 1
a2090 1
	      sprintf(errmsg,
d2134 1
a2134 1
	    sprintf(errmsg,
d2184 1
a2184 1
	    sprintf(errmsg,
d2212 1
a2212 1
	    sprintf(errmsg,
d2234 2
a2235 2
	    sprintf(errmsg, "%s keyword must use an underscore, not a dash",
	      keyname);
d2240 1
a2240 1
	    sprintf(errmsg,
d2262 1
a2262 1
	      sprintf(errmsg,
d2274 1
a2274 1
	    sprintf(errmsg,
d2308 1
a2308 1
	    sprintf(errmsg, "%s keyword is non-standard", keyname);
d2376 1
a2376 1
	    sprintf(errmsg,
d2416 1
a2416 1
	    sprintf(errmsg,
d2446 1
a2446 1
	    sprintf(errmsg,
d2460 2
a2461 2
	    sprintf(errmsg, "invalid alternate code, keyword resembles %s "
	      "but isn't", keyname);
d2522 1
a2522 1
	    sprintf(errmsg,
d2572 1
a2572 1
	    sprintf(errmsg,
d2600 1
a2600 1
	    sprintf(errmsg,
d2621 2
a2622 2
	  sprintf(errmsg, "%s keyword must use an underscore, not a dash",
	    keyname);
d2648 1
a2648 1
	    sprintf(errmsg, "the %s keyword is non-standard", keyname);
d2755 1
a2755 1
	        sprintf(errmsg, "axis number exceeds 99");
d2757 1
a2757 1
	        sprintf(errmsg, "parameter number exceeds 99");
d2759 1
a2759 1
	        sprintf(errmsg, "column number exceeds 999");
d2789 1
a2789 1
	      sprintf(errmsg, "internal parser ERROR, bad data type: %d",
d2990 1
a2990 1
	          strcpy(cptr, strtmp);
@


8.6.1.1
log
@WCSLIB 8.6 development branch.
@
text
@d22 1
a22 1
  $Id: wcsbth.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: wcsbth.l,v 8.6.1.1 2026/03/29 14:19:26 mcalabre Exp mcalabre $
d178 1
a178 1
  snprintf(strtmp, 80, "%s ", yytext); \
d1986 1
a1986 1
	    snprintf(errmsg, 80,
d2012 1
a2012 1
	    snprintf(errmsg, 80,
d2033 1
a2033 1
	    snprintf(errmsg, 80,
d2047 1
a2047 1
	    snprintf(errmsg, 80, "keyword looks very much like %s but isn't",
d2069 1
a2069 1
	    snprintf(errmsg, 80, "%s keyword is non-standard", keyname);
d2088 1
a2088 1
	      snprintf(errmsg, 80, "%s keyword is non-standard", keyname);
d2090 1
a2090 1
	      snprintf(errmsg, 80,
d2134 1
a2134 1
	    snprintf(errmsg, 80,
d2184 1
a2184 1
	    snprintf(errmsg, 80,
d2212 1
a2212 1
	    snprintf(errmsg, 80,
d2234 2
a2235 2
	    snprintf(errmsg, 80,
	      "%s keyword must use an underscore, not a dash", keyname);
d2240 1
a2240 1
	    snprintf(errmsg, 80,
d2262 1
a2262 1
	      snprintf(errmsg, 80,
d2274 1
a2274 1
	    snprintf(errmsg, 80,
d2308 1
a2308 1
	    snprintf(errmsg, 80, "%s keyword is non-standard", keyname);
d2376 1
a2376 1
	    snprintf(errmsg, 80,
d2416 1
a2416 1
	    snprintf(errmsg, 80,
d2446 1
a2446 1
	    snprintf(errmsg, 80,
d2460 2
a2461 2
	    snprintf(errmsg, 80, "invalid alternate code, keyword resembles "
	      "%s but isn't", keyname);
d2522 1
a2522 1
	    snprintf(errmsg, 80,
d2572 1
a2572 1
	    snprintf(errmsg, 80,
d2600 1
a2600 1
	    snprintf(errmsg, 80,
d2621 2
a2622 2
	  snprintf(errmsg, 80,
	    "%s keyword must use an underscore, not a dash", keyname);
d2648 1
a2648 1
	    snprintf(errmsg, 80, "the %s keyword is non-standard", keyname);
d2755 1
a2755 1
	        snprintf(errmsg, 80, "axis number exceeds 99");
d2757 1
a2757 1
	        snprintf(errmsg, 80, "parameter number exceeds 99");
d2759 1
a2759 1
	        snprintf(errmsg, 80, "column number exceeds 999");
d2789 1
a2789 1
	      snprintf(errmsg, 80, "internal parser ERROR, bad data type: %d",
d2990 1
a2990 1
	          strncpy(cptr, strtmp, 72);
@


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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.l,v 8.3.1.1 2024/05/13 16:35:39 mcalabre Exp mcalabre $
d2862 13
a2874 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;
a2875 1
	      strtmp[jx] = '\0';
@


8.4.1.1
log
@WCSLIB 8.4 development branch.
@
text
@d22 1
a22 1
  $Id: wcsbth.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: wcsbth.l,v 8.4.1.1 2024/10/28 13:58:41 mcalabre Exp mcalabre $
d2862 8
a2869 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';
d2871 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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.l,v 8.1.1.1 2023/07/05 17:15:00 mcalabre Exp mcalabre $
d2862 2
a2863 4
	    // Copy the keyvalue, skipping the initial quote.
	    strncpy(strtmp, yytext+1, 80);
	
	    // Remove the terminating quote.
@


8.2.1.1
log
@WCSLIB 8.2 development branch.
@
text
@d22 1
a22 1
  $Id: wcsbth.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: wcsbth.l,v 8.2.1.1 2023/11/16 10:05:57 mcalabre Exp mcalabre $
d2862 4
a2865 2
	    // Copy the keyvalue minus the quotes.
	    strncpy(strtmp, yytext+1, yyleng-2);
@


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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.l,v 7.12.1.1 2022/09/09 05:00:36 mcalabre Exp mcalabre $
d1909 54
d2862 13
a2874 2
	    // Read the keyvalue.
	    strcpy(strtmp, yytext+1);
a2883 1
	        if (ix) strtmp[ix-1] = '\0';
@


7.13.1.1
log
@WCSLIB 7.13 development branch.
@
text
@d22 1
a22 1
  $Id: wcsbth.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: wcsbth.l,v 7.13.1.1 2022/10/07 03:45:47 mcalabre Exp mcalabre $
a1905 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: wcsbth.l,v 7.13.1.2 2023/06/03 08:24:14 mcalabre Exp mcalabre $
d2862 2
a2863 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';
	    }
d2873 1
@


7.13.1.4
log
@(PLON_OBS, PLAT_OBS, PDIS_OBS) -> (BLON_OBS, BLAT_OBS, BDIS_OBS).
@
text
@d22 1
a22 1
  $Id: wcsbth.l,v 7.13.1.3 2023/06/03 14:21:54 mcalabre Exp mcalabre $
d1936 1
a1936 1
^BLON_OBS {
d1939 1
a1939 1
	  vptr    = &(auxtem.blon_obs);
d1941 1
a1941 1
	  keyname = "BLON_OBS";
d1945 1
a1945 1
^BLAT_OBS {
d1948 1
a1948 1
	  vptr    = &(auxtem.blat_obs);
d1950 1
a1950 1
	  keyname = "BLAT_OBS";
d1954 1
a1954 1
^BDIS_OBS {
d1957 1
a1957 1
	  vptr    = &(auxtem.bdis_obs);
d1959 1
a1959 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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.l,v 7.6.1.2 2021/07/02 08:32:59 mcalabre Exp mcalabre $
@


7.7.1.1
log
@WCSLIB 7.7 development branch.
@
text
@d22 1
a22 1
  $Id: wcsbth.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: wcsbth.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: wcsbth.l,v 7.5.1.1 2021/03/20 05:56:42 mcalabre Exp mcalabre $
d224 1
a224 1
	int  auxprm, inttmp;
d277 2
a278 2
	int altlin  = 0;
	char ptype  = ' ';
d282 2
a283 1
	int naux = 0;
d3014 1
a3080 1
	    auxprm  = 0;
@


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


7.6.1.2
log
@Fixed a bug in accounting the number of auxiliary WCS keywords processed.
@
text
@d22 1
a22 1
  $Id: wcsbth.l,v 7.6.1.1 2021/04/13 13:00:35 mcalabre Exp mcalabre $
d224 1
a224 1
	int    inttmp;
d277 2
a278 2
	int altlin = 0;
	char ptype = ' ';
d282 1
a282 2
	int auxprm = 0;
	int naux   = 0;
a3012 1
	  auxprm = 0;
d3079 1
@


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: wcsbth.l,v 7.4.1.4 2021/02/25 14:12:20 mcalabre Exp mcalabre $
@


7.5.1.1
log
@WCSLIB 7.5 development branch.
@
text
@d22 1
a22 1
  $Id: wcsbth.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: wcsbth.l,v 7.3.1.4 2021/01/28 12:29:30 mcalabre Exp mcalabre $
d76 1
d145 5
a149 3
static int wcsbth_scanner(char *header, int nkeyrec, int relax, int ctrl,
                          int keysel, int *colsel, int *nreject, int *nwcs,
                          struct wcsprm **wcs, yyscan_t yyscanner);
d151 3
a153 28
//----------------------------------------------------------------------------

int wcsbth(
  char *header,
  int nkeyrec,
  int relax,
  int ctrl,
  int keysel,
  int *colsel,
  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 = wcsbth_scanner(header, nkeyrec, relax, ctrl, keysel, colsel,
                          nreject, nwcs, wcs, yyscanner);
  yylex_destroy(yyscanner);

  return status;
}

//----------------------------------------------------------------------------
d161 2
a162 2
	  if (wcsbth_nkeyrec) { \
	    strncpy(inbuff, wcsbth_hdr, 80); \
d164 2
a165 2
	    wcsbth_hdr += 80; \
	    wcsbth_nkeyrec--; \
d172 3
d179 1
a179 1
  iz = strlen(strtmp); \
a181 4
// These global variables are required by YY_INPUT.
static char *wcsbth_hdr;
static int  wcsbth_nkeyrec;

d198 1
a219 4
// Used in preempting the call to exit() by yy_fatal_error().
jmp_buf wcsbth_abort_jmp_env;
#define exit(status) longjmp(wcsbth_abort_jmp_env, status)

d223 2
a224 11
	// Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka.
	char a;
	int  i, j, k, m, n;
	
	char *cptr, *errmsg, errtxt[80], exclude[1000], gotone, *hptr, *keep,
	     *keyname, *keyrec, ptype, strtmp[80];
	int  altlin, auxprm, ialt, icol, incl, imherit, inttmp, ipass, ipx,
	     itmp, ix, jx, keytype, naux, nother, nsel, npass, nvalid, status,
	     valtype;
	ptrdiff_t voff;
	size_t iz;
d226 2
a227 6
	void   *vptr, *wptr;
	struct wcsbth_alts alts;
	struct auxprm *auxp, auxtem;
	struct wcsprm *wcsp, wcstem;
	int (*chekval)(double);
	int (*special)(double *, const double *);
d229 2
a230 1
	// The data structures produced.
a233 4
	// Parameters used to implement YY_INPUT.
	wcsbth_hdr = header;
	wcsbth_nkeyrec = nkeyrec;
	
d235 3
a237 3
	keyrec = header;
	hptr = header;
	keep = 0x0;
d240 2
a241 3
	*nreject = 0;
	nvalid = 0;
	nother = 0;
d244 1
a244 1
	imherit = 1;
d249 7
a255 5
	// Keyword parameters.
	i = j = 0;
	n = k = 0;
	m = 0;
	a = ' ';
d258 1
d265 1
a265 1
	for (ialt = 0; ialt < 27; ialt++) {
d272 3
a274 3
	keytype =  0;
	valtype = -1;
	vptr    = 0x0;
d277 6
a282 6
	altlin  = 0;
	ptype   = ' ';
	chekval = 0x0;
	special = 0x0;
	auxprm  = 0;
	naux    = 0;
d285 4
a288 3
	nsel = colsel ? colsel[0] : 0;
	incl = (nsel > 0);
	for (icol = 0; icol < 1000; icol++) {
d291 2
a292 2
	for (icol = 1; icol <= abs(nsel); icol++) {
	  itmp = colsel[icol];
d300 3
a302 3
	itmp = keysel;
	keysel = 0;
	if (itmp) {
d312 6
a317 2
	ipass = 1;
	npass = 2;
d320 2
a321 2
	if (setjmp(wcsbth_abort_jmp_env)) {
	  return 4;
d1909 2
a1910 2
	  if (wcsbth_nkeyrec) {
	    wcsbth_nkeyrec = 0;
d2690 1
a2690 1
	      return 3;
d2808 1
a2808 1
	      strcpy(strtmp, yytext+1);
d2811 2
a2812 2
	    ix = 0;
	    for (jx = 0; jx < 72; jx++) {
d2848 2
a2849 1
	    gotone = 0;
d2854 1
d2858 1
a2858 1
	          voff = (char *)vptr - (char *)(&auxtem);
d2862 1
a2862 1
	          voff = (char *)vptr - (char *)(&wcstem);
d2872 1
a2872 1
	            ipx = (wcsp->npv)++;
d2909 1
a2909 1
	            ipx = wcsp->nps++;
d2922 1
a2922 1
	          cptr = (char *)wptr;
d3038 1
d3059 2
a3060 2
	    wcsbth_hdr = header;
	    wcsbth_nkeyrec = nkeyrec;
d3107 30
a3172 2
  int ialt, icol, mask, ncol;

d3178 1
a3178 1
  ncol = alts->ncol;
d3200 1
a3200 1
      return 2;
d3220 1
a3220 1
      return 2;
d3224 2
a3225 2
    for (icol = (1 + alts->ncol); icol < (1 + ncol); icol++) {
      for (ialt = 0; ialt < 27; ialt++) {
d3236 1
a3236 1
  ialt = 0;
d3273 1
a3273 1
    mask = 1 << ialt;
d3307 1
a3307 3
  int ialt, icol, inherit[27], ix, mask, ncol, npsmax, npvmax, status = 0;
  struct wcsprm *wcsp;

d3315 1
a3315 1
  ncol = alts->ncol;
d3320 1
a3320 1
      for (icol = 1; icol <= ncol; icol++) {
d3331 2
a3332 1
  for (ialt = 0; ialt < 27; ialt++) {
d3335 1
a3335 1
    for (icol = 1; icol <= ncol; icol++) {
d3383 1
a3383 1
      return 2;
d3387 1
a3387 1
    wcsp = *wcs;
d3389 2
a3390 2
    for (icol = 0; icol <= ncol; icol++) {
      for (ialt = 0; ialt < 27; ialt++) {
d3395 2
a3396 2
          npvmax = alts->npv[icol][ialt];
          npsmax = alts->nps[icol][ialt];
d3431 1
a3431 1
    for (ialt = 0; ialt < 27; ialt++) {
d3435 2
a3436 2
        npvmax = alts->pixnpv[ialt];
        npsmax = alts->pixnps[ialt];
d3456 1
a3456 1
        mask = (1 << ialt);
a3492 1
  int iwcs;
d3496 1
a3496 1
  iwcs = -1;
a3537 3
  int ix;
  struct wcsprm *wcsp;

d3540 1
a3540 1
  wcsp = wcs;
d3545 1
a3545 1
  for (ix = 0; ix < wcsp->naxis; ix++) {
d3623 1
a3623 1
  double beta, c = 299792458.0;
d3628 1
a3628 1
    beta = *vsource/c;
a3656 2
  int ialt, status;

d3662 1
a3662 1
  for (ialt = 0; ialt < *nwcs; ialt++) {
d3664 1
@


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


7.4.1.2
log
@Use of global variables (wcsbth_hdr, wcsbth_nkeyrec, and wcsbth_abort_jmp_env)
made the code thread-unsafe.  Modified to use the yyextra mechanism instead.
@
text
@d22 1
a22 1
  $Id: wcsbth.l,v 7.4.1.1 2021/01/31 02:26:24 mcalabre Exp mcalabre $
a75 1
%option extra-type="struct wcsbth_extra *"
d144 3
a146 5
// User data associated with yyscanner.
struct wcsbth_extra {
  // Values passed to YY_INPUT.
  char *hdr;
  int  nkeyrec;
d148 28
a175 3
  // Used in preempting the call to exit() by yy_fatal_error().
  jmp_buf abort_jmp_env;
};
d183 2
a184 2
	  if (yyextra->nkeyrec) { \
	    strncpy(inbuff, yyextra->hdr, 80); \
d186 2
a187 2
	    yyextra->hdr += 80; \
	    yyextra->nkeyrec--; \
a193 3
// Preempt the call to exit() by yy_fatal_error().
#define exit(status) longjmp(yyextra->abort_jmp_env, status);

d201 4
a220 1
static YY_DECL;
d242 4
d272 4
a353 4
	// User data associated with yyscanner.
	yyextra->hdr = header;
	yyextra->nkeyrec = nkeyrec;
	
d355 2
a356 2
	if (setjmp(yyextra->abort_jmp_env)) {
	  return WCSHDRERR_PARSER;
d1944 2
a1945 2
	  if (yyextra->nkeyrec) {
	    yyextra->nkeyrec = 0;
d2843 1
a2843 1
	    strcpy(strtmp, yytext+1);
d3091 2
a3092 2
	    yyextra->hdr = header;
	    yyextra->nkeyrec = nkeyrec;
a3136 30

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

int wcsbth(
  char *header,
  int nkeyrec,
  int relax,
  int ctrl,
  int keysel,
  int *colsel,
  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 wcsbth_extra extra;
  yyscan_t yyscanner;
  yylex_init_extra(&extra, &yyscanner);
  int status = wcsbth_scanner(header, nkeyrec, relax, ctrl, keysel, colsel,
                              nreject, nwcs, wcs, yyscanner);
  yylex_destroy(yyscanner);

  return status;
}
@


7.4.1.3
log
@Use preprocessor-defined symbolic function return codes.
@
text
@d22 1
a22 1
  $Id: wcsbth.l,v 7.4.1.2 2021/02/25 13:42:40 mcalabre Exp mcalabre $
d2699 1
a2699 1
	      return WCSHDRERR_BAD_COLUMN;
d3208 1
a3208 1
      return WCSHDRERR_MEMORY;
d3228 1
a3228 1
      return WCSHDRERR_MEMORY;
d3392 1
a3392 1
      return WCSHDRERR_MEMORY;
@


7.4.1.4
log
@Converted to C99-style intermingled variable declarations.
@
text
@d22 1
a22 1
  $Id: wcsbth.l,v 7.4.1.3 2021/02/25 14:07:35 mcalabre Exp mcalabre $
d179 1
a179 1
  size_t iz = strlen(strtmp); \
d223 11
a233 2
	char *errmsg, errtxt[80], *keyname, strtmp[80];
	int  auxprm, inttmp;
d235 6
a240 2
	struct auxprm auxtem;
	struct wcsprm wcstem;
d242 1
a242 2
	// Initialize returned values.
	*nreject = 0;
d247 3
a249 3
	char *keyrec = header;
	char *hptr = header;
	char *keep = 0x0;
d252 3
a254 2
	int nvalid = 0;
	int nother = 0;
d257 1
a257 1
	int imherit = 1;
d262 5
a266 7
	// Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka.
	int i = 0;
	int j = 0;
	int k = 0;
	int n = 0;
	int m = 0;
	char a = ' ';
a268 1
	struct wcsbth_alts alts;
d275 1
a275 1
	for (int ialt = 0; ialt < 27; ialt++) {
d282 3
a284 3
	int keytype =  0;
	int valtype = -1;
	void *vptr  = 0x0;
d287 6
a292 6
	int altlin  = 0;
	char ptype  = ' ';
	int (*chekval)(double) = 0x0;
	int (*special)(double *, const double *) = 0x0;
	struct auxprm *auxp = 0x0;
	int naux = 0;
d295 3
a297 4
	int nsel = colsel ? colsel[0] : 0;
	int incl = (nsel > 0);
	char exclude[1000];
	for (int icol = 0; icol < 1000; icol++) {
d300 2
a301 2
	for (int icol = 1; icol <= abs(nsel); icol++) {
	  int itmp = colsel[icol];
d309 3
a311 3
	if (keysel) {
	  int itmp = keysel;
	  keysel = 0;
d321 2
a322 2
	int ipass = 1;
	int npass = 2;
d2820 2
a2821 2
	    int ix = 0;
	    for (int jx = 0; jx < 72; jx++) {
d2857 1
a2857 2
	    int gotone = 0;
	    struct wcsprm *wcsp;
a2861 1
	        void *wptr;
d2865 1
a2865 1
	          ptrdiff_t voff = (char *)vptr - (char *)(&auxtem);
d2869 1
a2869 1
	          ptrdiff_t voff = (char *)vptr - (char *)(&wcstem);
d2879 1
a2879 1
	            int ipx = (wcsp->npv)++;
d2916 1
a2916 1
	            int ipx = wcsp->nps++;
d2929 1
a2929 1
	          char *cptr = (char *)wptr;
a3044 1
	    int status;
d3179 2
d3186 1
a3186 1
  int ncol = alts->ncol;
d3232 2
a3233 2
    for (int icol = (1 + alts->ncol); icol < (1 + ncol); icol++) {
      for (int ialt = 0; ialt < 27; ialt++) {
d3244 1
a3244 1
  int ialt = 0;
d3281 1
a3281 1
    int mask = 1 << ialt;
d3315 3
a3317 1
  int status = 0;
d3325 1
a3325 1
  int ialt, mask, ncol = alts->ncol;
d3330 1
a3330 1
      for (int icol = 1; icol <= ncol; icol++) {
d3341 1
a3341 2
  int inherit[27];
  for (int ialt = 0; ialt < 27; ialt++) {
d3344 1
a3344 1
    for (int icol = 1; icol <= ncol; icol++) {
d3396 1
a3396 1
    struct wcsprm *wcsp = *wcs;
d3398 2
a3399 2
    for (int icol = 0; icol <= ncol; icol++) {
      for (int ialt = 0; ialt < 27; ialt++) {
d3404 2
a3405 2
          int npvmax = alts->npv[icol][ialt];
          int npsmax = alts->nps[icol][ialt];
d3440 1
a3440 1
    for (int ialt = 0; ialt < 27; ialt++) {
d3444 2
a3445 2
        int npvmax = alts->pixnpv[ialt];
        int npsmax = alts->pixnps[ialt];
d3465 1
a3465 1
        int icol, ix, mask = (1 << ialt);
d3502 1
d3506 1
a3506 1
  int iwcs = -1;
d3548 3
d3553 1
a3553 1
  struct wcsprm *wcsp = wcs;
d3558 1
a3558 1
  for (int ix = 0; ix < wcsp->naxis; ix++) {
d3636 1
a3636 1
  const double c = 299792458.0;
d3641 1
a3641 1
    double beta = *vsource/c;
d3670 2
d3677 1
a3677 1
  for (int ialt = 0; ialt < *nwcs; ialt++) {
a3678 1
    int status;
@


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: wcsbth.l,v 7.2.1.2 2020/06/03 02:49:52 mcalabre Exp mcalabre $
d125 1
a125 1
			/* Codes used for keyvalue data types. */
d131 12
a142 12
			/* Bit masks used for keyword types:        */
#define IMGAUX  0x1	/* Auxiliary image header, e.g. LONPOLEa or */
			/* DATE-OBS.                                */
#define IMGAXIS 0x2	/* Image header with axis number, e.g.      */
			/* CTYPEia.                                 */
#define IMGHEAD 0x3	/* IMGAUX | IMGAXIS, i.e. image header of   */
			/* either type.                             */
#define BIMGARR 0x4	/* Binary table image array, e.g. iCTYna.   */
#define PIXLIST 0x8	/* Pixel list, e.g. TCTYna.                 */
#define BINTAB  0xC	/* BIMGARR | PIXLIST, i.e. binary table     */
			/* image array (without axis number) or     */
			/* pixel list, e.g. LONPna or OBSGXn.       */
d148 1
a148 1
/*--------------------------------------------------------------------------*/
d175 1
a175 1
/*--------------------------------------------------------------------------*/
d194 2
a195 2
/* A convenience macro to get around incompatibilities between unput() and
   yyless(): put yytext followed by a blank back onto the input stream. */
d201 1
a201 1
/* These global variables are required by YY_INPUT. */
d205 1
a205 1
/* Struct used internally for header bookkeeping. */
d220 1
a220 1
/* Internal helper functions. */
d232 1
a232 1
/* Helper functions for keywords that require special handling. */
d239 1
a239 1
/* Helper functions for keyvalue validity checking. */
d242 1
a242 1
/* Used in preempting the call to exit() by yy_fatal_error(). */
d249 1
a249 1
	/* Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka. */
d268 1
a268 1
	/* The data structures produced. */
d272 1
a272 1
	/* Parameters used to implement YY_INPUT. */
d276 1
a276 1
	/* Our handle on the input stream. */
d281 1
a281 1
	/* For keeping tallies of keywords found. */
d286 1
a286 1
	/* Used to flag image header keywords that are always inherited. */
d289 1
a289 1
	/* If strict, then also reject. */
d292 1
a292 1
	/* Keyword parameters. */
d298 1
a298 1
	/* Header bookkeeping. */
d311 1
a311 1
	/* For decoding the keyvalue. */
d316 1
a316 1
	/* For keywords that require special handling. */
d324 1
a324 1
	/* Selection by column number. */
d338 1
a338 1
	/* Selection by keyword type. */
d350 1
a350 1
	/* Control variables. */
d354 1
a354 1
	/* Return here via longjmp() invoked by yy_fatal_error(). */
d379 1
a379 1
	    /* Ignore this key type. */
d404 1
a404 1
	      /* Pretend we don't recognize it. */
d415 2
a416 2
	  /* Note that a blank in the sscanf() format string matches zero or
	     more of them in the input. */
d420 1
a420 1
	    /* Ignore this key type or column. */
d440 1
a440 1
	  /* Cross-reference supplier. */
d449 1
a449 1
	  /* Cross-reference consumer. */
d1247 1
a1247 1
	    /* Actually integer, but treated as float. */
d1303 1
a1303 1
	    /* Actually integer, but treated as float. */
d1850 1
a1850 1
	    /* Pretend we don't recognize it. */
d1971 1
a1971 1
	    /* Pretend we don't recognize it. */
d1980 1
a1980 1
	      /* Violates the basic FITS standard. */
d1986 1
a1986 1
	      /* Pretend we don't recognize it. */
d1997 1
a1997 1
	    /* Pretend we don't recognize it. */
d2005 2
a2006 2
	  /* Anything that has fallen through to this point must contain */
	  /* an invalid axis number. */
d2018 1
a2018 1
	    /* Pretend we don't recognize it. */
d2025 1
a2025 1
	    /* Looks too much like a FITS WCS keyword not to flag it. */
d2032 1
a2032 1
	    /* Pretend we don't recognize it. */
d2076 1
a2076 1
	    /* Pretend we don't recognize it. */
d2119 1
a2119 1
	    /* Pretend we don't recognize it. */
d2158 1
a2158 1
	      /* Pretend we don't recognize it. */
d2169 1
a2169 1
	    /* Pretend we don't recognize it. */
d2184 2
a2185 2
	  /* Anything that has fallen through to this point must contain */
	  /* an invalid axis number. */
d2197 1
a2197 1
	    /* Pretend we don't recognize it. */
d2225 1
a2225 1
	    /* Pretend we don't recognize it. */
d2231 1
a2231 1
	  /* This covers the defunct forms CD00i00j and PC00i00j. */
d2248 1
a2248 1
	      /* Pretend we don't recognize it. */
d2259 1
a2259 1
	    /* Pretend we don't recognize it. */
d2292 1
a2292 1
	    /* Pretend we don't recognize it. */
d2350 1
a2350 1
	      /* Pretend we don't recognize it. */
d2361 1
a2361 1
	    /* Pretend we don't recognize it. */
d2371 1
a2371 1
	    /* Let it go. */
d2401 1
a2401 1
	    /* Pretend we don't recognize it. */
d2413 1
a2413 1
	  /* Image-header keyword. */
d2431 1
a2431 1
	    /* Pretend we don't recognize it. */
d2438 1
a2438 1
	    /* Looks too much like a FITS WCS keyword not to flag it. */
d2445 1
a2445 1
	    /* Pretend we don't recognize it. */
d2494 1
a2494 1
	  /* Image-header keyword. */
d2507 1
a2507 1
	    /* Pretend we don't recognize it. */
d2546 1
a2546 1
	      /* Pretend we don't recognize it. */
d2557 1
a2557 1
	    /* Pretend we don't recognize it. */
d2573 2
a2574 2
	    /* Anything that has fallen through to this point must contain */
	    /* an invalid parameter. */
d2585 1
a2585 1
	    /* Pretend we don't recognize it. */
d2632 1
a2632 1
	    /* Pretend we don't recognize it. */
d2668 1
a2668 1
	  /* Invalid combinations will be flagged by <VALUE>. */
d2694 1
a2694 1
	    /* Pretend we don't recognize it. */
d2715 1
a2715 1
	  /* Do checks on i, j, m, n, k. */
d2717 1
a2717 1
	    /* Selection by keyword type. */
d2721 1
a2721 1
	    /* One or other column is not selected. */
d2723 2
a2724 2
	      /* For keywords such as TCn_ka, both columns must be excluded.
	         User error, so return immediately. */
d2744 1
a2744 1
	      /* Pretend we don't recognize it. */
d2749 1
a2749 1
	    /* Skip keyvalues that won't be inherited. */
d2754 2
a2755 2
	      /* IMGHEAD keytypes are always dealt with on the second pass. */
	      /* However, they must be re-parsed in order to report errors. */
d2786 1
a2786 1
	    /* Read the keyvalue. */
d2803 1
a2803 1
	    /* Read the keyvalue. */
d2825 1
a2825 1
	    /* Read the keyvalue as integer and fractional parts. */
d2842 1
a2842 1
	    /* Read the keyvalue. */
d2845 1
a2845 1
	    /* Squeeze out repeated quotes. */
d2873 1
a2873 1
	    /* Do first-pass bookkeeping. */
d2878 1
a2878 1
	    /* Store the value now that the keyrecord has been validated. */
d2882 1
a2882 1
	    /* Update each coordinate representation. */
d2889 1
a2889 1
	          /* Additional auxiliary parameter. */
d2894 1
a2894 1
	          /* A parameter that lives directly in wcsprm. */
d2903 1
a2903 1
	          /* Apply keyword parameterization. */
d2924 1
a2924 1
	          /* Flag the presence of PCi_ja, or CDi_ja and/or CROTAia. */
d2931 1
a2931 1
	            /* Split MJDREF and JDREF into integer and fraction.*/
d2940 1
a2940 1
	          /* Apply keyword parameterization. */
d3009 1
a3009 1
	      /* Preserve discards. */
d3047 1
a3047 1
	  /* Throw away the rest of the line and reset for the next one. */
d3069 1
a3069 1
	  /* End-of-input. */
d3178 1
a3178 1
    /* Keywords such as DATE-OBS go along for the ride. */
d3184 1
a3184 1
  /* Do we need to allocate memory for alts? */
d3187 3
a3189 3
      /* Can only happen if TFIELDS is missing or out-of-sequence.  If n and
         k are both zero then we may be processing an image header so leave
         ncol alone - the array will be realloc'd later if required. */
d3191 1
a3191 1
        /* The header is mangled, assume the worst. */
d3210 1
a3210 1
    /* Can only happen if TFIELDS or the WCS keyword is wrong; carry on. */
d3227 1
a3227 1
    /* Since realloc() doesn't initialize the extra memory. */
d3245 2
a3246 2
  /* A BINTAB keytype such as LONPna, in conjunction with an IMGAXIS keytype
     causes a table column to be recognized as an image array. */
d3248 1
a3248 1
    /* n == 0 is expected for IMGHEAD keywords. */
d3251 1
a3251 1
        /* Flag that an auxiliary keyword was seen. */
d3256 1
a3256 1
      /* Record the maximum axis number found. */
d3273 3
a3275 3
  /* BINTAB keytypes, which apply both to pixel lists as well as binary table
     image arrays, never contribute to recognizing a table column as a pixel
     list axis.  A PIXLIST keytype is required for that. */
d3279 1
a3279 1
    /* n > 0 for PIXLIST keytypes. */
d3283 1
a3283 1
    /* Used as a flag over all columns. */
d3320 1
a3320 1
  /* Determine the number of axes in each pixel list representation. */
d3334 1
a3334 1
  /* Find the total number of coordinate representations. */
d3342 1
a3342 1
        /* No BIMGARR keytype but there's at least one BINTAB. */
d3344 2
a3345 2
          /* There is an IMGAXIS keytype that we will inherit, so count this
             representation. */
d3354 1
a3354 1
          /* All IMGHEAD keywords are inherited for this ialt. */
d3358 1
a3358 1
            /* The extra axes are also inherited. */
d3367 1
a3367 1
    /* Count every "a" found in any IMGHEAD keyword... */
d3370 1
a3370 1
        /* ...but not if the IMGHEAD keywords will be inherited. */
d3378 1
a3378 1
    /* We need a struct for every "a" found in a PIXLIST keyword. */
d3386 1
a3386 1
    /* Allocate memory for the required number of wcsprm structs. */
d3391 1
a3391 1
    /* Initialize each wcsprm struct. */
d3397 2
a3398 2
          /* Image-header representations that are not for inheritance
             (icol == 0) or binary table image array representations. */
d3408 1
a3408 1
          /* Record the alternate version code. */
d3413 1
a3413 1
          /* Any additional auxiliary keywords present? */
d3420 1
a3420 1
          /* Record the table column number. */
d3423 2
a3424 2
          /* On the second pass alts->arridx[icol][27] indexes the array of
             wcsprm structs. */
d3430 1
a3430 1
          /* Signal that this column has no WCS for this "a". */
d3438 1
a3438 1
        /* Pixel lists representations. */
d3448 1
a3448 1
        /* Record the alternate version code. */
d3453 1
a3453 1
        /* Any additional auxiliary keywords present? */
d3460 1
a3460 1
        /* Record the pixel list column numbers. */
d3468 1
a3468 1
        /* alts->pixidx[] indexes the array of wcsprm structs. */
d3474 1
a3474 1
        /* Signal that this column is not a pixel list axis for this "a". */
d3504 2
a3505 2
    /* Note that a == 0 applies to every alternate, otherwise this
       loop simply determines the appropriate value of alts->ialt. */
d3510 2
a3511 2
        /* Image header keywords, n == 0, apply to all columns, otherwise this
           loop simply determines the appropriate value of alts->icol. */
d3516 1
a3516 1
      /* Break out of the loop to stop alts->ialt from being incremented. */
d3519 1
a3519 1
      /* Start from scratch for the next alts->ialt. */
d3571 1
a3571 1
  /* Set MJDREF from JDREF. */
d3588 1
a3588 1
  /* Set the integer part of MJDREF from JDREFI. */
d3600 1
a3600 1
  /* Set the fractional part of MJDREF from JDREFF. */
d3616 1
a3616 1
  /* If EQUINOXa is currently undefined then set it from EPOCHa. */
d3634 1
a3634 1
  /* If ZSOURCEa is currently undefined then set it from VSOURCEa. */
d3636 1
a3636 1
    /* Convert relativistic Doppler velocity to redshift. */
d3674 1
a3674 1
    /* Interpret -TAB header keywords. */
@


7.3.1.1
log
@WCSLIB 7.3 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 7.3.1.1 2020/06/03 03:38:10 mcalabre Exp mcalabre $
d128 1
a128 1
			// Codes used for keyvalue data types.
d134 12
a145 12
			// Bit masks used for keyword types:
#define IMGAUX  0x1	// Auxiliary image header, e.g. LONPOLEa or
			// DATE-OBS.
#define IMGAXIS 0x2	// Image header with axis number, e.g.
			// CTYPEia.
#define IMGHEAD 0x3	// IMGAUX | IMGAXIS, i.e. image header of
			// either type.
#define BIMGARR 0x4	// Binary table image array, e.g. iCTYna.
#define PIXLIST 0x8	// Pixel list, e.g. TCTYna.
#define BINTAB  0xC	// BIMGARR | PIXLIST, i.e. binary table
			// image array (without axis number) or
			// pixel list, e.g. LONPna or OBSGXn.
d151 1
a151 1
//----------------------------------------------------------------------------
d178 1
a178 1
//----------------------------------------------------------------------------
d197 2
a198 2
// A convenience macro to get around incompatibilities between unput() and
// yyless(): put yytext followed by a blank back onto the input stream.
d204 1
a204 1
// These global variables are required by YY_INPUT.
d208 1
a208 1
// Struct used internally for header bookkeeping.
d223 1
a223 1
// Internal helper functions.
d235 1
a235 1
// Helper functions for keywords that require special handling.
d242 1
a242 1
// Helper functions for keyvalue validity checking.
d245 1
a245 1
// Used in preempting the call to exit() by yy_fatal_error().
d252 1
a252 1
	// Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka.
d271 1
a271 1
	// The data structures produced.
d275 1
a275 1
	// Parameters used to implement YY_INPUT.
d279 1
a279 1
	// Our handle on the input stream.
d284 1
a284 1
	// For keeping tallies of keywords found.
d289 1
a289 1
	// Used to flag image header keywords that are always inherited.
d292 1
a292 1
	// If strict, then also reject.
d295 1
a295 1
	// Keyword parameters.
d301 1
a301 1
	// Header bookkeeping.
d314 1
a314 1
	// For decoding the keyvalue.
d319 1
a319 1
	// For keywords that require special handling.
d327 1
a327 1
	// Selection by column number.
d341 1
a341 1
	// Selection by keyword type.
d353 1
a353 1
	// Control variables.
d357 1
a357 1
	// Return here via longjmp() invoked by yy_fatal_error().
d382 1
a382 1
	    // Ignore this key type.
d407 1
a407 1
	      // Pretend we don't recognize it.
d418 2
a419 2
	  // Note that a blank in the sscanf() format string matches zero or
	  // more of them in the input.
d423 1
a423 1
	    // Ignore this key type or column.
d443 1
a443 1
	  // Cross-reference supplier.
d452 1
a452 1
	  // Cross-reference consumer.
d1250 1
a1250 1
	    // Actually integer, but treated as float.
d1306 1
a1306 1
	    // Actually integer, but treated as float.
d1853 1
a1853 1
	    // Pretend we don't recognize it.
d1974 1
a1974 1
	    // Pretend we don't recognize it.
d1983 1
a1983 1
	      // Violates the basic FITS standard.
d1989 1
a1989 1
	      // Pretend we don't recognize it.
d2000 1
a2000 1
	    // Pretend we don't recognize it.
d2008 2
a2009 2
	  // Anything that has fallen through to this point must contain
	  // an invalid axis number.
d2021 1
a2021 1
	    // Pretend we don't recognize it.
d2028 1
a2028 1
	    // Looks too much like a FITS WCS keyword not to flag it.
d2035 1
a2035 1
	    // Pretend we don't recognize it.
d2079 1
a2079 1
	    // Pretend we don't recognize it.
d2122 1
a2122 1
	    // Pretend we don't recognize it.
d2161 1
a2161 1
	      // Pretend we don't recognize it.
d2172 1
a2172 1
	    // Pretend we don't recognize it.
d2187 2
a2188 2
	  // Anything that has fallen through to this point must contain
	  // an invalid axis number.
d2200 1
a2200 1
	    // Pretend we don't recognize it.
d2228 1
a2228 1
	    // Pretend we don't recognize it.
d2234 1
a2234 1
	  // This covers the defunct forms CD00i00j and PC00i00j.
d2251 1
a2251 1
	      // Pretend we don't recognize it.
d2262 1
a2262 1
	    // Pretend we don't recognize it.
d2295 1
a2295 1
	    // Pretend we don't recognize it.
d2353 1
a2353 1
	      // Pretend we don't recognize it.
d2364 1
a2364 1
	    // Pretend we don't recognize it.
d2374 1
a2374 1
	    // Let it go.
d2404 1
a2404 1
	    // Pretend we don't recognize it.
d2416 1
a2416 1
	  // Image-header keyword.
d2434 1
a2434 1
	    // Pretend we don't recognize it.
d2441 1
a2441 1
	    // Looks too much like a FITS WCS keyword not to flag it.
d2448 1
a2448 1
	    // Pretend we don't recognize it.
d2497 1
a2497 1
	  // Image-header keyword.
d2510 1
a2510 1
	    // Pretend we don't recognize it.
d2549 1
a2549 1
	      // Pretend we don't recognize it.
d2560 1
a2560 1
	    // Pretend we don't recognize it.
d2576 2
a2577 2
	    // Anything that has fallen through to this point must contain
	    // an invalid parameter.
d2588 1
a2588 1
	    // Pretend we don't recognize it.
d2635 1
a2635 1
	    // Pretend we don't recognize it.
d2671 1
a2671 1
	  // Invalid combinations will be flagged by <VALUE>.
d2697 1
a2697 1
	    // Pretend we don't recognize it.
d2718 1
a2718 1
	  // Do checks on i, j, m, n, k.
d2720 1
a2720 1
	    // Selection by keyword type.
d2724 1
a2724 1
	    // One or other column is not selected.
d2726 2
a2727 2
	      // For keywords such as TCn_ka, both columns must be excluded.
	      // User error, so return immediately.
d2747 1
a2747 1
	      // Pretend we don't recognize it.
d2752 1
a2752 1
	    // Skip keyvalues that won't be inherited.
d2757 2
a2758 2
	      // IMGHEAD keytypes are always dealt with on the second pass.
	      // However, they must be re-parsed in order to report errors.
d2789 1
a2789 1
	    // Read the keyvalue.
d2806 1
a2806 1
	    // Read the keyvalue.
d2828 1
a2828 1
	    // Read the keyvalue as integer and fractional parts.
d2845 1
a2845 1
	    // Read the keyvalue.
d2848 1
a2848 1
	    // Squeeze out repeated quotes.
d2876 1
a2876 1
	    // Do first-pass bookkeeping.
d2881 1
a2881 1
	    // Store the value now that the keyrecord has been validated.
d2885 1
a2885 1
	    // Update each coordinate representation.
d2892 1
a2892 1
	          // Additional auxiliary parameter.
d2897 1
a2897 1
	          // A parameter that lives directly in wcsprm.
d2906 1
a2906 1
	          // Apply keyword parameterization.
d2927 1
a2927 1
	          // Flag the presence of PCi_ja, or CDi_ja and/or CROTAia.
d2934 1
a2934 1
	            // Split MJDREF and JDREF into integer and fraction.
d2943 1
a2943 1
	          // Apply keyword parameterization.
d3012 1
a3012 1
	      // Preserve discards.
d3050 1
a3050 1
	  // Throw away the rest of the line and reset for the next one.
d3072 1
a3072 1
	  // End-of-input.
d3181 1
a3181 1
    // Keywords such as DATE-OBS go along for the ride.
d3187 1
a3187 1
  // Do we need to allocate memory for alts?
d3190 3
a3192 3
      // Can only happen if TFIELDS is missing or out-of-sequence.  If n and
      // k are both zero then we may be processing an image header so leave
      // ncol alone - the array will be realloc'd later if required.
d3194 1
a3194 1
        // The header is mangled, assume the worst.
d3213 1
a3213 1
    // Can only happen if TFIELDS or the WCS keyword is wrong; carry on.
d3230 1
a3230 1
    // Since realloc() doesn't initialize the extra memory.
d3248 2
a3249 2
  // A BINTAB keytype such as LONPna, in conjunction with an IMGAXIS keytype
  // causes a table column to be recognized as an image array.
d3251 1
a3251 1
    // n == 0 is expected for IMGHEAD keywords.
d3254 1
a3254 1
        // Flag that an auxiliary keyword was seen.
d3259 1
a3259 1
      // Record the maximum axis number found.
d3276 3
a3278 3
  // BINTAB keytypes, which apply both to pixel lists as well as binary table
  // image arrays, never contribute to recognizing a table column as a pixel
  // list axis.  A PIXLIST keytype is required for that.
d3282 1
a3282 1
    // n > 0 for PIXLIST keytypes.
d3286 1
a3286 1
    // Used as a flag over all columns.
d3323 1
a3323 1
  // Determine the number of axes in each pixel list representation.
d3337 1
a3337 1
  // Find the total number of coordinate representations.
d3345 1
a3345 1
        // No BIMGARR keytype but there's at least one BINTAB.
d3347 2
a3348 2
          // There is an IMGAXIS keytype that we will inherit, so count this
          // representation.
d3357 1
a3357 1
          // All IMGHEAD keywords are inherited for this ialt.
d3361 1
a3361 1
            // The extra axes are also inherited.
d3370 1
a3370 1
    // Count every "a" found in any IMGHEAD keyword...
d3373 1
a3373 1
        // ...but not if the IMGHEAD keywords will be inherited.
d3381 1
a3381 1
    // We need a struct for every "a" found in a PIXLIST keyword.
d3389 1
a3389 1
    // Allocate memory for the required number of wcsprm structs.
d3394 1
a3394 1
    // Initialize each wcsprm struct.
d3400 2
a3401 2
          // Image-header representations that are not for inheritance
          // (icol == 0) or binary table image array representations.
d3411 1
a3411 1
          // Record the alternate version code.
d3416 1
a3416 1
          // Any additional auxiliary keywords present?
d3423 1
a3423 1
          // Record the table column number.
d3426 2
a3427 2
          // On the second pass alts->arridx[icol][27] indexes the array of
          // wcsprm structs.
d3433 1
a3433 1
          // Signal that this column has no WCS for this "a".
d3441 1
a3441 1
        // Pixel lists representations.
d3451 1
a3451 1
        // Record the alternate version code.
d3456 1
a3456 1
        // Any additional auxiliary keywords present?
d3463 1
a3463 1
        // Record the pixel list column numbers.
d3471 1
a3471 1
        // alts->pixidx[] indexes the array of wcsprm structs.
d3477 1
a3477 1
        // Signal that this column is not a pixel list axis for this "a".
d3507 2
a3508 2
    // Note that a == 0 applies to every alternate, otherwise this
    // loop simply determines the appropriate value of alts->ialt.
d3513 2
a3514 2
        // Image header keywords, n == 0, apply to all columns, otherwise this
        // loop simply determines the appropriate value of alts->icol.
d3519 1
a3519 1
      // Break out of the loop to stop alts->ialt from being incremented.
d3522 1
a3522 1
      // Start from scratch for the next alts->ialt.
d3574 1
a3574 1
  // Set MJDREF from JDREF.
d3591 1
a3591 1
  // Set the integer part of MJDREF from JDREFI.
d3603 1
a3603 1
  // Set the fractional part of MJDREF from JDREFF.
d3619 1
a3619 1
  // If EQUINOXa is currently undefined then set it from EPOCHa.
d3637 1
a3637 1
  // If ZSOURCEa is currently undefined then set it from VSOURCEa.
d3639 1
a3639 1
    // Convert relativistic Doppler velocity to redshift.
d3677 1
a3677 1
    // Interpret -TAB header keywords.
@


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: wcsbth.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: wcsbth.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: wcsbth.l,v 7.1.1.1 2019/12/31 13:28:19 mcalabre Exp mcalabre $
d1211 12
a1222 3
^DATEREF" " {
	  valtype = STRING;
	  vptr    = wcstem.dateref;
d1224 3
a1226 2
	  keyname = "DATEREF";
	  BEGIN(CCCCCCCC);
d1229 12
a1240 3
^MJDREF"  " {
	  valtype = FLOAT2;
	  vptr    = wcstem.mjdref;
d1242 3
a1244 2
	  keyname = "MJDREF";
	  BEGIN(CCCCCCCC);
d1247 13
a1259 4
^MJDREFI" " {
	  /* Actually integer, but treated as float. */
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
d1261 3
a1263 2
	  keyname = "MJDREFI";
	  BEGIN(CCCCCCCC);
d1266 12
a1277 3
^MJDREFF" " {
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref + 1;
d1279 3
a1281 2
	  keyname = "MJDREFF";
	  BEGIN(CCCCCCCC);
d1284 6
a1289 4
^JDREF"   " {
	  valtype = FLOAT2;
	  vptr    = wcstem.mjdref;
	  special = wcsbth_jdref;
d1291 10
a1300 2
	  keyname = "JDREF";
	  BEGIN(CCCCCCCC);
d1303 14
a1316 5
^JDREFI"  " {
	  /* Actually integer, but treated as float. */
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
	  special = wcsbth_jdrefi;
d1318 3
a1320 2
	  keyname = "JDREFI";
	  BEGIN(CCCCCCCC);
d1323 13
a1335 4
^JDREFF"  " {
	  valtype = FLOAT;
	  vptr    = wcstem.mjdref;
	  special = wcsbth_jdreff;
d1337 3
a1339 2
	  keyname = "JDREFF";
	  BEGIN(CCCCCCCC);
@


7.2.1.1
log
@WCSLIB 7.2 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 7.2.1.1 2020/03/09 07:34:50 mcalabre Exp mcalabre $
d1211 3
a1213 5
^DATEREF" " |
^DATE-REF {
	  if ((yytext[4] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = STRING;
	    vptr    = wcstem.dateref;
d1215 2
a1216 10
	    keyname = "DATEREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the DATE-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d1219 3
a1221 5
^MJDREF"  " |
^MJD-REF" " {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT2;
	    vptr    = wcstem.mjdref;
d1223 2
a1224 10
	    keyname = "MJDREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d1227 4
a1230 6
^MJDREFI" " |
^MJD-REFI {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    /* Actually integer, but treated as float. */
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
d1232 2
a1233 10
	    keyname = "MJDREFI";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REFI keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d1236 3
a1238 5
^MJDREFF" " |
^MJD-REFF {
	  if ((yytext[3] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref + 1;
d1240 2
a1241 10
	    keyname = "MJDREFF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the MJD-REFF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d1244 4
a1247 6
^JDREF"   " |
^JD-REF"  " {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT2;
	    vptr    = wcstem.mjdref;
	    special = wcsbth_jdref;
d1249 2
a1250 10
	    keyname = "JDREF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d1253 5
a1257 7
^JDREFI"  " |
^JD-REFI {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    /* Actually integer, but treated as float. */
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
	    special = wcsbth_jdrefi;
d1259 2
a1260 10
	    keyname = "JDREFI";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REFI keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
d1263 4
a1266 6
^JDREFF"  " |
^JD-REFF {
	  if ((yytext[2] == 'R') || (relax & WCSHDR_DATEREF)) {
	    valtype = FLOAT;
	    vptr    = wcstem.mjdref;
	    special = wcsbth_jdreff;
d1268 2
a1269 10
	    keyname = "JDREFF";
	    BEGIN(CCCCCCCC);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the JD-REFF keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
@


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: wcsbth.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: wcsbth.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: wcsbth.l,v 6.3.1.1 2019/07/12 07:34:37 mcalabre Exp mcalabre $
d117 1
d201 2
a202 2
  itmp = strlen(strtmp); \
  while (itmp) unput(strtmp[--itmp]);
d230 1
a230 1
static int wcsbth_init1(struct wcsbth_alts *alts, int *nwcs,
d258 5
a262 2
	int  altlin, ialt, icol, incl, imherit, inttmp, ipass, ipx, itmp, ix,
	     jx, keytype, nother, nsel, npass, nvalid, status, valtype, voff;
d266 1
d324 2
d1830 46
d2821 10
a2830 2
	        voff = (char *)vptr - (char *)(&wcstem);
	        wptr = (void *)((char *)wcsp + voff);
d2978 2
d3004 1
a3004 1
	    if ((status = wcsbth_init1(&alts, nwcs, wcs)) ||
d3044 1
d3239 1
d3346 7
d3384 7
@


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


6.4.1.2
log
@Use size_t and ptrdiff_t data types correctly to quell warnings from
Microsoft Visual C++ (MSVC).
@
text
@d25 1
a25 1
  $Id: wcsbth.l,v 6.4.1.1 2019/08/15 09:31:29 mcalabre Exp mcalabre $
a116 1
#include <stddef.h>
d200 2
a201 2
  iz = strlen(strtmp); \
  while (iz) unput(strtmp[--iz]);
d258 1
a258 3
	     jx, keytype, nother, nsel, npass, nvalid, status, valtype;
	ptrdiff_t voff;
	size_t iz;
@


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: wcsbth.l,v 6.4.1.2 2019/12/16 03:11:53 mcalabre Exp mcalabre $
d230 1
a230 1
static int wcsbth_init1(struct wcsbth_alts *alts, int auxprm, int *nwcs,
d258 2
a259 3
	int  altlin, auxprm, ialt, icol, incl, imherit, inttmp, ipass, ipx,
	     itmp, ix, jx, keytype, naux, nother, nsel, npass, nvalid, status,
	     valtype;
a264 1
	struct auxprm *auxp, auxtem;
a321 2
	auxprm  = 0;
	naux    = 0;
a1825 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);
	}

d2771 2
a2772 10
	        if (auxprm) {
	          /* Additional auxiliary parameter. */
	          auxp = wcsp->aux;
	          voff = (char *)vptr - (char *)(&auxtem);
	          wptr = (void *)((char *)auxp + voff);
	        } else {
	          /* A parameter that lives directly in wcsprm. */
	          voff = (char *)vptr - (char *)(&wcstem);
	          wptr = (void *)((char *)wcsp + voff);
	        }
a2919 2
	  naux += auxprm;
	
d2944 1
a2944 1
	    if ((status = wcsbth_init1(&alts, naux, nwcs, wcs)) ||
a2983 1
	    auxprm  = 0;
a3177 1
  int naux,
a3283 7
          /* Any additional auxiliary keywords present? */
          if (naux) {
            if (wcsauxi(1, wcsp)) {
              return WCSHDRERR_MEMORY;
            }
          }

a3314 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: wcsbth.l,v 6.4.1.3 2019/12/31 02:27:13 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: wcsbth.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: wcsbth.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: wcsbth.l,v 6.1.1.1 2018/10/19 08:36:15 mcalabre Exp mcalabre $
d74 1
@


6.2.1.1
log
@WCSLIB 6.2 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.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: wcsbth.l,v 6.2.1.3 2019/07/08 06:55:39 mcalabre Exp mcalabre $
a73 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: wcsbth.l,v 5.20.1.2 2018/10/19 06:35:42 mcalabre Exp mcalabre $
@


6.1.1.1
log
@WCSLIB 6.1 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 5.19.1.1 2018/07/26 15:41:40 mcalabre Exp mcalabre $
d110 1
a110 1
%x VALUE INTEGER_VAL FLOAT_VAL STRING_VAL
d129 2
a130 1
#define STRING  2
d137 3
a139 3
#define IMGHEAD 0x3	/* Image header of either type.             */
#define BIMGARR 0x4	/* Binary table image array with axis       */
			/* number, e.g. iCTYna.                     */
d141 3
a143 3
#define BINTAB  0xC	/* Shared binary table image array (without */
			/* axis number) or pixel list, e.g. LONPna  */
			/* or OBSGXn.                               */
d203 2
a204 6
char *wcsbth_hdr;
int  wcsbth_nkeyrec;

/* Used in preempting the call to exit() by yy_fatal_error(). */
jmp_buf wcsbth_abort_jmp_env;
#define exit(status) longjmp(wcsbth_abort_jmp_env, status)
d221 6
a226 5
int wcsbth_pass1(int keytype, int i, int j, int n, int k, char a, char ptype,
        struct wcsbth_alts *alts);
int wcsbth_init1(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);

struct wcsprm *wcsbth_idx(struct wcsprm *wcs, struct wcsbth_alts *alts,
d228 11
a238 1
int wcsbth_colax(struct wcsprm *wcs, struct wcsbth_alts *alts, int k, char a);
d240 2
a241 2
int wcsbth_epoch(double *wptr, double epoch);
int wcsbth_vsource(double *wptr, double vsource);
d243 3
a245 1
int wcsbth_final(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
d256 3
a258 3
	int  altlin, ialt, icol, incl, inttmp, ipass, ipx, itmp, ix, jx,
	     keytype, nother, nsel, npass, nvalid, status, valtype, voff;
	double dbltmp;
d262 2
a263 1
	int (*special)(double *, double);
d283 3
d316 1
d453 1
a453 1

d746 1
d761 1
d902 26
d1048 126
a1173 2
^DATE-AVG |
^DAVG   {
d1175 1
a1175 1
	  vptr    = wcstem.dateavg;
d1179 1
a1179 1
	    keyname = "DATE-AVG";
d1182 2
a1183 2
	    keyname = "DAVGna";
	    BEGIN(CCCCn);
d1187 85
a1274 1
	
d1278 1
d1291 1
a1291 1
	    keyname = "DOBSna";
d1295 1
a1295 1
	    errmsg = "DOBSna keyword is non-standard";
d1303 4
a1306 2
^EPOCH{ALT}"  " {
	  sscanf(yytext, "EPOCH%c", &a);
d1308 8
a1315 3
	  if (relax & WCSHDR_strict) {
	    errmsg = "the EPOCH keyword is deprecated, use EQUINOXa";
	    BEGIN(ERROR);
d1317 14
a1330 4
	  } else if (a == ' ' || (relax & WCSHDR_EPOCHa)) {
	    valtype = FLOAT;
	    vptr    = &(wcstem.equinox);
	    special = wcsbth_epoch;
d1332 8
a1339 8
	    unput(a);
	
	    keyname = "EPOCH";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "EPOCH keyword may not have an alternate version code";
	    BEGIN(ERROR);
d1341 5
d1347 2
a1348 1
	    BEGIN(DISCARD);
d1352 1
a1352 2
^EQUINOX |
^EQUI	{
d1354 2
a1355 1
	  vptr    = &(wcstem.equinox);
d1357 2
a1358 7
	  if (yyleng == 7) {
	    keyname = "EQUINOXa";
	    BEGIN(CCCCCCCa);
	  } else {
	    keyname = "EQUIna";
	    BEGIN(CCCCna);
	  }
d1376 91
a1466 2
^MJD-OBS" " |
^MJDOB	{
d1468 3
a1470 1
	  vptr    = &(wcstem.mjdobs);
d1472 2
a1473 8
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "MJD-OBS";
	    BEGIN(CCCCCCCC);
	  } else {
	    keyname = "MJDOn";
	    BEGIN(CCCCCn);
	  }
d1521 98
d1626 1
d1642 1
d1648 1
a1648 1

d1654 13
a1666 4
^SPECSYS |
^SPEC	{
	  valtype = STRING;
	  vptr    = wcstem.specsys;
d1668 2
a1669 2
	  if (yyleng == 7) {
	    keyname = "SPECSYSa";
d1671 5
d1677 1
a1677 2
	    keyname = "SPECna";
	    BEGIN(CCCCna);
d1681 4
a1684 4
^SSYSOBS |
^SOBS	{
	  valtype = STRING;
	  vptr    = wcstem.ssysobs;
d1687 2
a1688 1
	    keyname = "SSYSOBSa";
d1691 1
a1691 1
	    keyname = "SOBSna";
d1696 2
a1697 2
^SSYSSRC |
^SSRC	{
d1699 1
a1699 1
	  vptr    = wcstem.ssyssrc;
d1702 1
a1702 1
	    keyname = "SSYSSRCa";
d1705 1
a1705 1
	    keyname = "SSRCna";
d1710 4
a1713 4
^VELANGL |
^VANG	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.velangl);
d1716 1
a1716 1
	    keyname = "VELANGLa";
d1719 1
a1719 1
	    keyname = "VANGna";
a1737 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);
	  }
	}

d1780 16
a1795 3
^WCSNAME |
^WCSN	 |
^TWCS	{
d1797 1
a1797 1
	  vptr    = wcstem.wcsname;
d1800 1
a1800 1
	    keyname = "WCSNAMEa";
a1801 1
	
d1803 1
a1803 5
	    if (*yytext == 'W') {
	      keyname = "WCSNna";
	    } else {
	      keyname = "TWCSna";
	    }
d1808 2
a1809 2
^ZSOURCE |
^ZSOU	{
d1811 1
a1811 1
	  vptr    = &(wcstem.zsource);
d1814 1
a1814 1
	    keyname = "ZSOURCEa";
d1817 1
a1817 1
	    keyname = "ZSOUna";
d2293 1
a2293 1
	  if (relax & (WCSHDR_AUXIMG | WCSHDR_ALLIMG)) {
d2642 2
d2685 22
d2711 1
a2711 1
<FLOAT_VAL>. {
d2790 1
a2790 1
	            special(wptr, dbltmp);
d2801 9
d2931 1
d2965 2
d2978 1
d3418 45
d3466 1
a3466 1
int wcsbth_epoch(double *equinox, double epoch)
d3471 1
a3471 1
    *equinox = epoch;
d3482 1
a3482 1
int wcsbth_vsource(double *zsource, double vsource)
d3490 1
a3490 1
    beta = vsource/c;
d3495 11
@


5.20.1.1
log
@WCSLIB 5.20 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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).  According to WCS
Papers III and VII, certain global image header keywords are permitted in
binary table headers and are expected to be inherited by image arrays and
pixel lists.  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: wcsbth.l,v 5.20.1.1 2018/10/05 05:33:33 mcalabre Exp mcalabre $
d110 1
a110 1
%x VALUE INTEGER_VAL FLOAT_VAL FLOAT2_VAL STRING_VAL
d129 1
a129 2
#define FLOAT2  2
#define STRING  3
d136 3
a138 3
#define IMGHEAD 0x3	/* IMGAUX | IMGAXIS, i.e. image header of   */
			/* either type.                             */
#define BIMGARR 0x4	/* Binary table image array, e.g. iCTYna.   */
d140 3
a142 3
#define BINTAB  0xC	/* BIMGARR | PIXLIST, i.e. binary table     */
			/* image array (without axis number) or     */
			/* pixel list, e.g. LONPna or OBSGXn.       */
d202 6
a207 2
static char *wcsbth_hdr;
static int  wcsbth_nkeyrec;
d224 5
a228 6
/* Internal helper functions. */
static int wcsbth_colax(struct wcsprm *wcs, struct wcsbth_alts *alts, int k,
        char a);
static int wcsbth_final(struct wcsbth_alts *alts, int *nwcs,
        struct wcsprm **wcs);
static struct wcsprm *wcsbth_idx(struct wcsprm *wcs, struct wcsbth_alts *alts,
d230 1
a230 11
static int wcsbth_init1(struct wcsbth_alts *alts, int *nwcs,
        struct wcsprm **wcs);
static int wcsbth_pass1(int keytype, int i, int j, int n, int k, char a,
        char ptype, struct wcsbth_alts *alts);

/* Helper functions for keywords that require special handling. */
static int wcsbth_jdref(double *wptr,   const double *jdref);
static int wcsbth_jdrefi(double *wptr,  const double *jdrefi);
static int wcsbth_jdreff(double *wptr,  const double *jdreff);
static int wcsbth_epoch(double *wptr,   const double *epoch);
static int wcsbth_vsource(double *wptr, const double *vsource);
d232 2
a233 2
/* Helper functions for keyvalue validity checking. */
static int wcsbth_timepixr(double timepixr);
d235 1
a235 3
/* Used in preempting the call to exit() by yy_fatal_error(). */
jmp_buf wcsbth_abort_jmp_env;
#define exit(status) longjmp(wcsbth_abort_jmp_env, status)
d246 3
a248 3
	int  altlin, ialt, icol, incl, imherit, inttmp, ipass, ipx, itmp, ix,
	     jx, keytype, nother, nsel, npass, nvalid, status, valtype, voff;
	double dbltmp, dbl2tmp[2];
d252 1
a252 2
	int (*chekval)(double);
	int (*special)(double *, const double *);
a271 3
	/* Used to flag image header keywords that are always inherited. */
	imherit = 1;
	
a301 1
	chekval = 0x0;
d438 1
a438 1
	
a730 1
	    imherit = 0;
a744 1
	    imherit = 0;
a884 26
^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";
	    imherit = 0;
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VELREF keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

^{I1}CZP  |
^{I1}CZPH {
	  valtype = FLOAT;
	  vptr    = &(wcstem.czphs);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCZPna";
	    BEGIN(iCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "iCZPHn";
	    BEGIN(iCCCCn);
	  }
	}

^TCZP	|
^TCZPH	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.czphs);
	
	  if (yyleng == 4) {
	    keyname = "TCZPna";
	    BEGIN(TCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "TCZPHn";
	    BEGIN(TCCCCn);
	  }
	}

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

^{I1}CPR  |
^{I1}CPER {
	  valtype = FLOAT;
	  vptr    = &(wcstem.cperi);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    keyname = "iCPRna";
	    BEGIN(iCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "iCPERn";
	    BEGIN(iCCCCn);
	  }
	}

^TCPR	|
^TCPER	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.cperi);
	
	  if (yyleng == 4) {
	    keyname = "TCPRna";
	    BEGIN(TCCCna);
	  } else {
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    keyname = "TCPERn";
	    BEGIN(TCCCCn);
	  }
	}

^WCSNAME |
^WCSN	 |
^TWCS	{
d1008 1
a1008 29
	  vptr    = wcstem.wcsname;
	
	  if (yyleng == 7) {
	    keyname = "WCSNAMEa";
	    imherit = 0;
	    BEGIN(CCCCCCCa);
	
	  } else {
	    if (*yytext == 'W') {
	      keyname = "WCSNna";
	    } else {
	      keyname = "TWCSna";
	    }
	    BEGIN(CCCCna);
	  }
	}

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

^TREFPOS" " |
^TRPOS  {
	  valtype = STRING;
	  vptr    = wcstem.trefpos;
d1012 1
a1012 1
	    keyname = "TREFPOS";
d1015 2
a1016 2
	    keyname = "TRPOSn";
	    BEGIN(CCCCCn);
a1019 100
^TREFDIR" " |
^TRDIR  {
	  valtype = STRING;
	  vptr    = wcstem.trefdir;
	
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "TREFDIR";
	    BEGIN(CCCCCCCC);
	  } else {
	    keyname = "TRDIRn";
	    BEGIN(CCCCCn);
	  }
	}

^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 = wcsbth_jdref;
	
	  keyname = "JDREF";
	  BEGIN(CCCCCCCC);
	}

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

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

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

d1023 1
a1026 1
	  imherit = 0;
d1039 1
a1039 1
	    keyname = "DOBSn";
d1043 1
a1043 1
	    errmsg = "DOBSn keyword is non-standard";
d1051 16
a1066 4
^DATE-BEG {
	  valtype = STRING;
	  vptr    = wcstem.datebeg;
	  if (ctrl < -10) keep = keyrec;
d1068 3
a1070 8
	  keyname = "DATE-BEG";
	  BEGIN(CCCCCCCC);
	}

^DATE-AVG |
^DAVG   {
	  valtype = STRING;
	  vptr    = wcstem.dateavg;
a1071 4
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "DATE-AVG";
	    BEGIN(CCCCCCCC);
d1073 1
a1073 2
	    keyname = "DAVGn";
	    BEGIN(CCCCn);
d1077 2
a1078 11
^DATE-END {
	  valtype = STRING;
	  vptr    = wcstem.dateend;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "DATE-END";
	  BEGIN(CCCCCCCC);
	}

^MJD-OBS" " |
^MJDOB	{
d1080 1
a1080 1
	  vptr    = &(wcstem.mjdobs);
d1082 3
a1084 5
	  if (yyleng == 8) {
	    if (ctrl < -10) keep = keyrec;
	    keyname = "MJD-OBS";
	    imherit = 0;
	    BEGIN(CCCCCCCC);
d1086 2
a1087 2
	    keyname = "MJDOBn";
	    BEGIN(CCCCCn);
a1090 9
^MJD-BEG" " {
	  valtype = FLOAT;
	  vptr    = &(wcstem.mjdbeg);
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "MJD-BEG";
	  BEGIN(CCCCCCCC);
	}

d1106 2
a1107 1
^MJD-END" " {
d1109 1
a1109 2
	  vptr    = &(wcstem.mjdend);
	  if (ctrl < -10) keep = keyrec;
d1111 8
a1118 93
	  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 = wcsbth_timepixr;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "TIMEPIXR";
	  BEGIN(CCCCCCCC);
a1165 98
^OBSGEO-L {
	  valtype = FLOAT;
	  vptr    = wcstem.obsgeo + 3;
	  if (ctrl < -10) keep = keyrec;
	
	  keyname = "OBSGEO-L";
	  BEGIN(CCCCCCCC);
	}

^OBSGL{I1}"  " |
^OBSGL{I2}" "  |
^OBSGL{I3} {
	  valtype = STRING;
	  vptr    = wcstem.obsgeo + 3;
	
	  if (relax & WCSHDR_OBSGLBHn) {
	    yyless(5);
	
	    keyname = "OBSGLn";
	    BEGIN(CCCCCn);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "OBSGLn keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

^OBSGB{I1}"  " |
^OBSGB{I2}" "  |
^OBSGB{I3} {
	  valtype = STRING;
	  vptr    = wcstem.obsgeo + 3;
	
	  if (relax & WCSHDR_OBSGLBHn) {
	    yyless(5);
	
	    keyname = "OBSGBn";
	    BEGIN(CCCCCn);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "OBSGBn keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

^OBSGH{I1}"  " |
^OBSGH{I2}" "  |
^OBSGH{I3} {
	  valtype = STRING;
	  vptr    = wcstem.obsgeo + 3;
	
	  if (relax & WCSHDR_OBSGLBHn) {
	    yyless(5);
	
	    keyname = "OBSGHn";
	    BEGIN(CCCCCn);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "OBSGHn keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

a1172 1
	    imherit = 0;
a1187 1
	    imherit = 0;
d1193 1
a1193 1
	
d1199 4
a1202 2
^EPOCH{ALT}"  " {
	  sscanf(yytext, "EPOCH%c", &a);
d1204 2
a1205 13
	  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 = wcsbth_epoch;
	
	    unput(a);
	
	    keyname = "EPOCH";
	    imherit = 0;
a1206 5
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "EPOCH keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
d1208 2
a1209 1
	    BEGIN(DISCARD);
d1213 4
a1216 4
^EQUINOX |
^EQUI	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.equinox);
d1219 1
a1219 2
	    keyname = "EQUINOXa";
	    imherit = 0;
d1222 1
a1222 1
	    keyname = "EQUIna";
d1227 2
a1228 2
^SPECSYS |
^SPEC	{
d1230 1
a1230 1
	  vptr    = wcstem.specsys;
d1233 1
a1233 1
	    keyname = "SPECSYSa";
d1236 1
a1236 1
	    keyname = "SPECna";
d1241 4
a1244 4
^SSYSOBS |
^SOBS	{
	  valtype = STRING;
	  vptr    = wcstem.ssysobs;
d1247 1
a1247 1
	    keyname = "SSYSOBSa";
d1250 1
a1250 1
	    keyname = "SOBSna";
d1269 25
d1336 5
a1340 4
^ZSOURCE |
^ZSOU	{
	  valtype = FLOAT;
	  vptr    = &(wcstem.zsource);
d1343 1
a1343 1
	    keyname = "ZSOURCEa";
a1344 10
	  } else {
	    keyname = "ZSOUna";
	    BEGIN(CCCCna);
	  }
	}

^SSYSSRC |
^SSRC	{
	  valtype = STRING;
	  vptr    = wcstem.ssyssrc;
a1345 3
	  if (yyleng == 7) {
	    keyname = "SSYSSRCa";
	    BEGIN(CCCCCCCa);
d1347 5
a1351 1
	    keyname = "SSRCna";
d1356 2
a1357 2
^VELANGL |
^VANG	{
d1359 1
a1359 1
	  vptr    = &(wcstem.velangl);
d1362 1
a1362 1
	    keyname = "VELANGLa";
d1365 1
a1365 1
	    keyname = "VANGna";
d1841 1
a1841 1
	  if (imherit || (relax & (WCSHDR_AUXIMG | WCSHDR_ALLIMG))) {
a2189 2
	    } else if (valtype == FLOAT2) {
	      BEGIN(FLOAT2_VAL);
d2231 1
a2231 6
	    if (chekval && chekval(dbltmp)) {
	      errmsg = "invalid keyvalue";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(COMMENT);
	    }
a2239 17
<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);
	}

d2314 1
a2314 1
	            special(wptr, &dbltmp);
a2324 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];
	            }
	
a2445 1
	  chekval = 0x0;
a2478 2
	    imherit = 1;
	
a2489 1
	    chekval = 0x0;
a2928 45
* Interpret the JDREF, JDREFI, and JDREFF keywords.
*---------------------------------------------------------------------------*/

int wcsbth_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 wcsbth_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 wcsbth_jdreff(double *mjdref, const double *jdreff)

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

  return 0;
}


/*----------------------------------------------------------------------------
d2932 1
a2932 1
int wcsbth_epoch(double *equinox, const double *epoch)
d2937 1
a2937 1
    *equinox = *epoch;
d2948 1
a2948 1
int wcsbth_vsource(double *zsource, const double *vsource)
d2956 1
a2956 1
    beta = *vsource/c;
a2960 11
}


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

int wcsbth_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: wcsbth.l,v 5.18.1.1 2018/01/10 08:33:04 mcalabre Exp mcalabre $
@


5.19.1.1
log
@WCSLIB 5.19 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 5.17.1.4 2018/01/10 08:25:34 mcalabre Exp mcalabre $
@


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


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: wcsbth.l,v 5.16.1.2 2017/09/12 13:30:44 mcalabre Exp mcalabre $
d77 1
d144 36
a179 3
#define YY_DECL int wcsbth(char *header, int nkeyrec, int relax, int ctrl, \
                           int keysel, int *colsel, int *nreject, int *nwcs, \
			   struct wcsprm **wcs)
a252 1
	int yylex_destroy(void);
a2151 1
	      yylex_destroy();
a2455 1
	      yylex_destroy();
d2492 1
a2492 1
	    yyrestart(yyin);
a2494 1
	    yylex_destroy();
a2768 4
    /* Record the current values of NPVMAX and NPSMAX. */
    npvmax = wcsnpv(-1);
    npsmax = wcsnps(-1);

d2778 4
a2781 3
          wcsnpv(alts->npv[icol][ialt]);
          wcsnps(alts->nps[icol][ialt]);
          if ((status = wcsini(1, (int)(alts->arridx[icol][ialt]), wcsp))) {
d2811 4
a2814 3
        wcsnpv(alts->pixnpv[ialt]);
        wcsnps(alts->pixnps[ialt]);
        if ((status = wcsini(1, (int)(alts->pixidx[ialt]), wcsp))) {
a2841 4

    /* Restore the original values of NPVMAX and NPSMAX. */
    wcsnpv(npvmax);
    wcsnps(npsmax);
@


5.17.1.1
log
@WCSLIB 5.17 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 5.17.1.1 2017/09/18 08:45:59 mcalabre Exp mcalabre $
a76 1
%option reentrant
d143 3
a145 36
static int wcsbth_scanner(char *header, int nkeyrec, int relax, int ctrl,
                          int keysel, int *colsel, int *nreject, int *nwcs,
                          struct wcsprm **wcs, yyscan_t yyscanner);

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

int wcsbth(
  char *header,
  int nkeyrec,
  int relax,
  int ctrl,
  int keysel,
  int *colsel,
  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 = wcsbth_scanner(header, nkeyrec, relax, ctrl, keysel, colsel,
                          nreject, nwcs, wcs, yyscanner);
  yylex_destroy(yyscanner);

  return status;
}

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

#define YY_DECL int wcsbth_scanner(char *header, int nkeyrec, int relax, \
 int ctrl, int keysel, int *colsel, int *nreject, int *nwcs, \
 struct wcsprm **wcs, yyscan_t yyscanner)
d219 1
d2119 1
d2424 1
d2461 1
a2461 1
	    yyrestart(yyin, yyscanner);
d2464 1
@


5.17.1.3
log
@Modified wcsbth_init() to use wcsinit() in place of wcsini().
@
text
@d25 1
a25 1
  $Id: wcsbth.l,v 5.17.1.2 2017/12/05 01:38:46 mcalabre Exp mcalabre $
d2769 4
d2782 3
a2784 4
          npvmax = alts->npv[icol][ialt];
          npsmax = alts->nps[icol][ialt];
          if ((status = wcsinit(1, (int)(alts->arridx[icol][ialt]), wcsp,
                                npvmax, npsmax, -1))) {
d2814 3
a2816 4
        npvmax = alts->pixnpv[ialt];
        npsmax = alts->pixnps[ialt];
        if ((status = wcsinit(1, (int)(alts->pixidx[ialt]), wcsp, npvmax,
                              npsmax, -1))) {
d2844 4
@


5.17.1.4
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2018, Mark Calabretta
d25 1
a25 1
  $Id: wcsbth.l,v 5.17.1.3 2017/12/05 07:46:39 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: wcsbth.l,v 5.15.1.2 2017/01/15 04:14:00 mcalabre Exp mcalabre $
d2197 1
a2197 1
	    wcsutil_str2double(yytext, "%lf", &dbltmp);
@


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


5.16.1.2
log
@Revised argument list to wcsutil_str2double().
@
text
@d25 1
a25 1
  $Id: wcsbth.l,v 5.16.1.1 2017/01/15 04:28:59 mcalabre Exp mcalabre $
d2197 1
a2197 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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.l,v 5.12.1.2 2016/01/25 05:17:04 mcalabre Exp mcalabre $
@


5.13.1.1
log
@WCSLIB 5.13 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 5.11.1.1 2015/10/18 09:16:27 mcalabre Exp mcalabre $
@


5.12.1.1
log
@WCSLIB 5.12 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 5.12.1.1 2015/11/15 02:16:14 mcalabre Exp mcalabre $
@


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: wcsbth.l,v 5.10.1.1 2015/10/09 08:22:35 mcalabre Exp mcalabre $
@


5.11.1.1
log
@WCSLIB 5.11 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 5.9.1.1 2015/07/21 09:28:07 mcalabre Exp mcalabre $
@


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


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: wcsbth.l,v 5.8.1.1 2015/07/08 11:07:18 mcalabre Exp mcalabre $
@


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


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: wcsbth.l,v 5.7.1.1 2015/06/29 02:47:24 mcalabre Exp mcalabre $
@


5.8.1.1
log
@WCSLIB 5.8 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 5.6.1.1 2015/06/14 07:14:44 mcalabre Exp mcalabre $
@


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


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: wcsbth.l,v 5.5.1.1 2015/05/05 13:21:00 mcalabre Exp mcalabre $
@


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


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: wcsbth.l,v 5.4.1.1 2015/04/21 14:44:28 mcalabre Exp mcalabre $
@


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


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: wcsbth.l,v 5.3.1.1 2015/04/21 02:54:02 mcalabre Exp mcalabre $
@


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


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: wcsbth.l,v 5.2.1.1 2015/04/15 12:39:14 mcalabre Exp mcalabre $
@


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


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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.l,v 4.25.1.4 2015/04/03 01:52:32 mcalabre Exp mcalabre $
@


5.0.1.1
log
@WCSLIB 5.0 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 4.24.1.1 2014/09/18 15:28:09 mcalabre Exp mcalabre $
d38 1
a38 1
* wcsbth() may be invoked with an option that causes it to recognise the
d79 5
a83 1
I0	[0-9]
d94 1
a94 1
FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
d97 3
d163 3
a165 3
  sprintf(stmp, "%s ", yytext); \
  itmp = strlen(stmp); \
  while (itmp) unput(stmp[--itmp]);
d198 2
a199 2
int wcsbth_epoch(void *wptr);
int wcsbth_vsource(void *wptr);
d210 5
a214 4
	char *cptr, *errmsg, errtxt[80], exclude[1000], *extkey, *hptr, ptype,
	     stmp[16];
	int  altlin, ialt, icol, incl, ipass, ipx, itmp, ix, jx, keytype,
	     nsel, npass, status, valtype, voff;
d218 1
a218 1
	int (*special)(void *);
d230 1
d232 3
d236 5
d267 2
a268 2
	altlin = 0;
	ptype  = ' ';
d315 1
a315 1
	      errmsg = "Duplicate or out-of-sequence TFIELDS keyword";
d325 1
a325 3
	  keytype = IMGAXIS;
	
	  if (!(keytype & keysel)) {
d331 13
a343 3
	      if (ipass == 1) {
	        sscanf(yytext, "WCSAXES%c= %d", &a, &i);
	        wcsbth_pass1(IMGAXIS, i, 0, 0, 0, a, ' ', &alts);
a345 2
	      BEGIN(FLUSH);
	
d347 1
a347 1
	      errmsg = "Image-header keyword WCSAXESa in binary table";
d360 1
a360 1
	  keytype = BIMGARR;
d366 1
a366 1
	  if (!(keytype & keysel) || exclude[n]) {
d369 5
d375 6
a380 4
	    if (ipass == 1) {
	      wcsbth_pass1(BIMGARR, i, 0, n, 0, a, ' ', &alts);
	    }
	    BEGIN(FLUSH);
d388 2
a389 2
	  keytype = BIMGARR;
	  errmsg = "Cross-references are not currently implemented";
d397 2
a398 2
	  keytype = BIMGARR;
	  errmsg = "Cross-references are not currently implemented";
d404 3
a406 3
	  vptr = &(wcstem.crpix);
	
	  extkey = "CRPIXja";
d413 1
a413 1
	  vptr = &(wcstem.crpix);
d418 1
d421 1
a421 1
	    extkey = "jCRPXn";
d429 1
a429 1
	  vptr = &(wcstem.crpix);
d432 1
d435 1
a435 1
	    extkey = "TCRPXn";
d442 1
a442 1
	  vptr = &(wcstem.pc);
d445 1
a445 1
	  extkey = "PCi_ja";
d451 2
a452 2
	  vptr = &(wcstem.pc);
	  altlin = 1;
d456 1
d463 2
a464 2
	  vptr = &(wcstem.pc);
	  altlin = 1;
d467 1
d470 1
a470 1
	    extkey = "TPCn_ka";
d477 2
a478 2
	  vptr = &(wcstem.cd);
	  altlin = 2;
d480 1
a480 1
	  extkey = "CDi_ja";
d486 2
a487 2
	  vptr = &(wcstem.cd);
	  altlin = 2;
d491 1
d498 2
a499 2
	  vptr = &(wcstem.cd);
	  altlin = 2;
d502 1
d505 1
a505 1
	    extkey = "TCDn_ka";
d512 1
a512 1
	  vptr = &(wcstem.cdelt);
d514 1
a514 1
	  extkey = "CDELTia";
d521 1
a521 1
	  vptr = &(wcstem.cdelt);
d526 1
d529 1
a529 1
	    extkey = "iCDLTn";
d537 1
a537 1
	  vptr = &(wcstem.cdelt);
d540 1
d543 1
a543 1
	    extkey = "TCDLTn";
d550 2
a551 2
	  vptr = &(wcstem.crota);
	  altlin = 4;
d553 1
a553 1
	  extkey = "CROTAi";
d559 2
a560 2
	  vptr = &(wcstem.crota);
	  altlin = 4;
d564 1
a564 1
	  extkey = "iCROTn";
d570 2
a571 2
	  vptr = &(wcstem.crota);
	  altlin = 4;
d573 1
a573 1
	  extkey = "TCROTn";
d579 1
a579 1
	  vptr = &(wcstem.cunit);
d581 1
a581 1
	  extkey = "CUNITia";
d588 1
a588 1
	  vptr = &(wcstem.cunit);
d593 1
d596 1
a596 1
	    extkey = "iCUNIn";
d604 1
a604 1
	  vptr = &(wcstem.cunit);
d607 1
d610 1
a610 1
	    extkey = "TCUNIn";
d617 1
a617 1
	  vptr = &(wcstem.ctype);
d619 1
a619 1
	  extkey = "CTYPEia";
d626 1
a626 1
	  vptr = &(wcstem.ctype);
d631 1
d634 1
a634 1
	    extkey = "iCTYPn";
d642 1
a642 1
	  vptr = &(wcstem.ctype);
d645 1
d648 1
a648 1
	    extkey = "TCTYPn";
d655 1
a655 1
	  vptr = &(wcstem.crval);
d657 1
a657 1
	  extkey = "CRVALia";
d664 1
a664 1
	  vptr = &(wcstem.crval);
d669 1
d672 1
a672 1
	    extkey = "iCRVLn";
d680 1
a680 1
	  vptr = &(wcstem.crval);
d683 1
d686 1
a686 1
	    extkey = "TCRVLn";
d694 1
a694 1
	  vptr = &(wcstem.lonpole);
d697 1
a697 1
	    extkey = "LONPOLEa";
d700 1
d708 1
a708 1
	  vptr = &(wcstem.latpole);
d711 1
a711 1
	    extkey = "LATPOLEa";
d714 1
d719 1
a720 1
^RESTFREQ |
d723 1
a723 1
	  vptr = &(wcstem.restfrq);
d726 11
a736 3
	    unput(' ');
	    extkey = "RESTFREQ";
	    BEGIN(CCCCCCCa);
d738 1
a738 1
	    extkey = "RESTFRQa";
d740 1
d742 1
d750 1
a750 1
	  vptr = &(wcstem.restwav);
d753 1
a753 1
	    extkey = "RESTWAVa";
d756 1
d763 2
a764 2
	  vptr = &(wcstem.pv);
	  ptype = 'v';
d766 1
a766 1
	  extkey = "PVi_ma";
d773 2
a774 2
	  vptr = &(wcstem.pv);
	  ptype = 'v';
d779 1
d782 1
a782 1
	    extkey = "iPVn_ma";
d790 2
a791 2
	  vptr = &(wcstem.pv);
	  ptype = 'v';
d794 1
d797 1
a797 1
	    extkey = "TPVn_ma";
d804 2
a805 2
	  vptr = &(wcstem.pv);
	  ptype = 'v';
d807 1
d813 2
a814 2
	  vptr = &(wcstem.ps);
	  ptype = 's';
d816 1
a816 1
	  extkey = "PSi_ma";
d823 2
a824 2
	  vptr = &(wcstem.ps);
	  ptype = 's';
d829 1
d832 1
a832 1
	    extkey = "iPSn_ma";
d840 2
a841 2
	  vptr = &(wcstem.ps);
	  ptype = 's';
d844 1
d847 1
a847 1
	    extkey = "TPSn_ma";
d854 1
a854 1
	  vptr = &(wcstem.cname);
d856 1
a856 1
	  extkey = "CNAMEia";
d863 1
a863 1
	  vptr = &(wcstem.cname);
d868 1
d872 1
a872 1
	    extkey = "iCNAMn";
d880 1
a880 1
	  vptr = &(wcstem.cname);
d883 1
d887 1
a887 1
	    extkey = "TCNAMn";
d894 1
a894 1
	  vptr = &(wcstem.crder);
d896 1
a896 1
	  extkey = "CRDERia";
d903 1
a903 1
	  vptr = &(wcstem.crder);
d908 1
d912 1
a912 1
	    extkey = "iCRDEn";
d920 1
a920 1
	  vptr = &(wcstem.crder);
d923 1
d927 1
a927 1
	    extkey = "TCRDEn";
d934 1
a934 1
	  vptr = &(wcstem.csyer);
d936 1
a936 1
	  extkey = "CSYERia";
d943 1
a943 1
	  vptr = &(wcstem.csyer);
d948 1
d952 1
a952 1
	    extkey = "iCSYEn";
d960 1
a960 1
	  vptr = &(wcstem.csyer);
d963 1
d967 1
a967 1
	    extkey = "TCSYEn";
d975 1
a975 1
	  vptr = wcstem.dateavg;
d978 2
a979 1
	    extkey = "DATE-AVG";
d982 1
d989 3
a991 1
	  vptr = wcstem.dateobs;
d993 1
a993 1
	  extkey = "DATE-OBS";
d1000 3
d1004 1
a1004 2
	    valtype = STRING;
	    vptr = wcstem.dateobs;
d1006 1
a1006 1
	    yyless(4);
d1009 4
d1014 1
a1014 7
	    keytype = BINTAB;
	    if (relax & WCSHDR_reject) {
	      errmsg = "DOBSna keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1021 5
a1025 1
	  if (a == ' ' || (relax & WCSHDR_EPOCHa)) {
d1027 1
a1027 1
	    vptr = &(wcstem.equinox);
d1031 2
a1032 1
	    extkey = "EPOCH";
d1035 4
d1040 1
a1040 7
	    keytype = IMGAUX;
	    if (relax & WCSHDR_reject) {
	      errmsg = "EPOCH keyword may not have an alternate version code";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1047 1
a1047 1
	  vptr = &(wcstem.equinox);
d1050 1
a1050 1
	    extkey = "EQUINOXa";
d1053 1
d1061 1
a1061 1
	  vptr = &(wcstem.mjdavg);
d1064 2
a1065 1
	    extkey = "MJD-AVG";
d1068 1
d1076 1
a1076 1
	  vptr = &(wcstem.mjdobs);
d1079 2
a1080 1
	    extkey = "MJD-OBS";
d1083 1
d1091 1
a1091 1
	  vptr = wcstem.obsgeo;
d1094 2
a1095 1
	    extkey = "OBSGEO-X";
d1098 1
d1106 1
a1106 1
	  vptr = wcstem.obsgeo + 1;
d1109 2
a1110 1
	    extkey = "OBSGEO-Y";
d1113 1
d1121 1
a1121 1
	  vptr = wcstem.obsgeo + 2;
d1124 2
a1125 1
	    extkey = "OBSGEO-Z";
d1128 1
d1136 1
a1136 1
	  vptr = wcstem.radesys;
d1139 1
a1139 1
	    extkey = "RADESYSa";
d1142 1
d1150 1
a1150 1
	    vptr = wcstem.radesys;
d1153 2
a1154 1
	    extkey = "RADECSYS";
d1157 4
d1162 1
a1162 7
	    keytype = IMGAUX;
	    if (relax & WCSHDR_reject) {
	      errmsg = "RADECSYS keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1169 1
a1169 1
	  vptr = wcstem.specsys;
d1172 1
a1172 1
	    extkey = "SPECSYSa";
d1175 1
d1183 1
a1183 1
	  vptr = wcstem.ssysobs;
d1186 1
a1186 1
	    extkey = "SSYSOBSa";
d1189 1
d1197 1
a1197 1
	  vptr = wcstem.ssyssrc;
d1200 1
a1200 1
	    extkey = "SSYSSRCa";
d1203 1
d1208 2
a1209 2
^VELOSYS |
^VSYS	{
d1211 1
a1211 1
	  vptr = &(wcstem.velosys);
d1214 1
a1214 1
	    extkey = "VELOSYSa";
d1217 1
d1222 2
a1223 2
^VELANGL |
^VANG	{
d1225 1
a1225 1
	  vptr = &(wcstem.velangl);
d1228 1
a1228 1
	    extkey = "VELANGLa";
d1231 1
d1239 5
a1243 1
	  if (a == ' ' || (relax & WCSHDR_VELREFa)) {
d1245 1
a1245 1
	    vptr = &(wcstem.velref);
d1248 2
a1249 1
	    extkey = "VELREF";
d1252 4
d1257 1
a1257 7
	    keytype = IMGAUX;
	    if (relax & WCSHDR_reject) {
	      errmsg = "VELREF keyword may not have an alternate version code";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1264 1
a1264 1
	    vptr = &(wcstem.zsource);
d1268 2
a1269 1
	    extkey = "VSOURCEa";
d1272 4
d1277 1
a1277 7
	    keytype = IMGAUX;
	    if (relax & WCSHDR_reject) {
	      errmsg = "VSOURCEa keyword is deprecated";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1286 1
a1286 1
	    vptr = &(wcstem.zsource);
d1290 1
d1293 4
d1298 2
a1299 8
	    keytype = BINTAB;
	    if (relax & WCSHDR_reject) {
	      errmsg = "VSOUna keyword is deprecated";
	      BEGIN(ERROR);
	    } else {
	      /* Pretend we don't recognize it. */
	      BEGIN(DISCARD);
	    }
d1307 1
a1307 1
	  vptr = wcstem.wcsname;
d1310 1
a1310 1
	    extkey = "WCSNAMEa";
d1312 1
d1314 5
d1326 1
a1326 1
	  vptr = &(wcstem.zsource);
d1329 1
a1329 1
	    extkey = "ZSOURCEa";
d1332 1
a1337 1
	  yyless(0);
d1340 1
a1340 1
	    errmsg = "Keyrecords following the END keyrecord were ignored";
a1347 1
	  yyless(0);
a1352 2
	  /* Image-header keyword. */
	  keytype = IMGAXIS;
d1355 1
d1361 1
a1361 1
	      "Image-header keyword %s in binary table", extkey);
d1370 2
a1371 3
<CCCCCia>{I3} {
	  /* Invalid axis number in image-header keyword. */
	  keytype = IMGAXIS;
d1373 51
a1423 3
	    /* Will also be flagged by <VALUE> as invalid. */
	    sscanf(yytext, "%3d", &i);
	    BEGIN(VALUE);
d1440 6
d1447 1
a1447 8
	    keytype = (YY_START == iCCCCn) ? BIMGARR : PIXLIST;
	    if (relax & WCSHDR_reject) {
	      errmsg = errtxt;
	      sprintf(errmsg, "%s keyword is non-standard", extkey);
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1459 4
a1462 12
	  } else {
	    keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
	    if (relax & WCSHDR_reject) {
	      errmsg = errtxt;
	      if (!vptr) {
	        sprintf(errmsg, "%s keyword is non-standard", extkey);
	      } else {
	        sprintf(errmsg,
	          "%s keyword may not have an alternate version code", extkey);
	      }
	      BEGIN(ERROR);
	
d1464 2
a1465 2
	      /* Pretend we don't recognize it. */
	      BEGIN(DISCARD);
d1467 5
a1500 1
	  /* Image-header keyword. */
d1509 1
a1509 1
	      "Image-header keyword %s in binary table", extkey);
d1518 21
a1538 7
<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 number in image-header keyword. */
d1540 77
a1616 4
	    /* Will be flagged by <VALUE> as invalid. */
	    sscanf(yytext, "%d_%d", &i, &j);
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
d1624 1
a1624 1
<CCi_ja>{I0}{6} {
d1626 19
a1644 6
	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
	    sscanf(yytext, "%3d%3d", &i, &j);
	    a = ' ';
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
d1648 2
a1649 2
	    sprintf(errmsg, "Defunct form of %si_ja keyword",
	                     (altlin==1) ? "PC" : "CD");
d1682 1
a1682 1
	    sprintf(errmsg, "%s keyword is non-standard", extkey);
d1724 23
a1746 11
<CROTAi>{I1}"  " |
<CROTAi>{I2}" " {
	  yyless(0);
	  BEGIN(CCCCCia);
	}

<CROTAi>{I1}[A-Z]" " |
<CROTAi>{I2}[A-Z] {
	  if (relax & WCSHDR_CROTAia) {
	    yyless(0);
	    BEGIN(CCCCCia);
d1749 3
a1751 1
	    errmsg = "CROTAn keyword may not have an alternate version code";
d1761 7
a1767 1
	  BEGIN(DISCARD);
d1791 1
a1791 1
	      "%s keyword may not have an alternate version code", extkey);
d1821 1
a1821 1
	      "Image-header keyword %s in binary table", extkey);
d1831 11
a1841 1
	  BEGIN(DISCARD);
d1884 1
a1884 1
<CCi_ma>{I1}_{I0}{ALT}"  " |
d1886 1
a1886 1
<CCi_ma>{I2}_{I0}{ALT}" " |
d1897 1
a1897 1
	      "Image-header keyword %s in binary table", extkey);
d1906 21
a1926 7
<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 parameter in image-header keyword. */
d1928 49
a1976 4
	    /* Will be flagged by <VALUE> as invalid. */
	    sscanf(yytext, "%d_%d", &i, &m);
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
d1984 16
d2004 1
a2004 1
<iCCn_ma>{I1}_{I0}{ALT}" " |
d2007 1
a2007 1
<iCCn_ma>{I2}_{I0}{ALT}    |
d2009 2
a2010 2
<iCCn_ma>{I3}_{I0}         |
<TCCn_ma>{I1}_{I0}{ALT}" " |
d2013 1
a2013 1
<TCCn_ma>{I2}_{I0}{ALT}    |
d2015 1
a2015 1
<TCCn_ma>{I3}_{I0} {
d2022 1
a2022 1
	    sprintf(errmsg, "%s keyword is non-standard", extkey);
d2036 1
a2036 1
<iCn_ma>{I1}_{I0}{ALT}"  " |
d2039 1
a2039 1
<iCn_ma>{I2}_{I0}{ALT}" "  |
d2041 2
a2042 2
<iCn_ma>{I3}_{I0}{ALT}     |
<TCn_ma>{I1}_{I0}{ALT}"  " |
d2045 1
a2045 1
<TCn_ma>{I2}_{I0}{ALT}" "  |
d2047 1
a2047 1
<TCn_ma>{I3}_{I0}{ALT} {
d2057 1
a2057 1
<iCn_ma>{I4}_{I0} |
d2061 1
a2061 1
<TCn_ma>{I4}_{I0} {
d2075 1
a2075 1
<PROJPm>{I0}"  " {
d2084 1
a2084 1
	    errmsg = "PROJPn keyword is defunct";
d2093 11
d2130 1
a2130 1
	        sprintf(errmsg, "Axis number exceeds 99");
d2132 1
a2132 1
	        sprintf(errmsg, "Parameter number exceeds 99");
d2134 1
a2134 1
	        sprintf(errmsg, "Column number exceeds 999");
d2147 6
a2152 8
	  } else if (ipass == 3 && (keytype & IMGHEAD)) {
	    /* IMGHEAD keytypes are always dealt with on the second pass. */
	    BEGIN(FLUSH);
	
	  } else if (vptr) {
	    alts.icol = 0;
	    alts.ialt = 0;
	    voff = (char *)vptr - (char *)(&wcstem);
d2162 1
a2162 1
	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
a2165 4
	
	  } else {
	    errmsg = "Internal parser ERROR, null pointer";
	    BEGIN(ERROR);
d2170 1
a2170 1
	  errmsg = "Invalid KEYWORD = VALUE syntax";
d2176 1
a2176 3
	    /* Do first-pass bookkeeping. */
	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
	    BEGIN(FLUSH);
d2179 2
a2180 11
	    /* Update each coordinate representation. */
	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
	      wptr = (void *)((char *)wcsp + voff);
	
	      /* Read the keyvalue. */
	      if (special) {
	        special(wptr);
	      } else {
	        sscanf(yytext, "%d", (int *)wptr);
	      }
	    }
d2187 1
a2187 1
	  errmsg = "An integer value was expected";
d2193 1
a2193 3
	    /* Do first-pass bookkeeping. */
	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
	    BEGIN(FLUSH);
d2196 15
a2210 3
	    /* Update each coordinate representation. */
	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
	      wptr = (void *)((char *)wcsp + voff);
d2212 3
a2214 10
	      /* Apply keyword parameterization. */
	      if (ptype == 'v') {
	        ipx = wcsp->npv++;
	        wcsp->pv[ipx].i = i;
	        wcsp->pv[ipx].m = m;
	        wptr = &(wcsp->pv[ipx].value);
	
	      } else if (j) {
	        /* Is the de-reference necessary? */
	        wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis) + (j - 1);
d2216 5
a2220 2
	      } else if (i) {
	        wptr = *((double **)wptr) + (i - 1);
d2223 5
a2227 5
	      /* Read the keyvalue. */
	      if (special) {
	        special(wptr);
	      } else {
	        wcsutil_str2double(yytext, "%lf", (double *)wptr);
d2230 1
a2230 5
	      /* Flag the presence of PC, or CD and/or CROTA. */
	      if (altlin) {
	        wcsp->altlin |= altlin;
	        altlin = 0;
	      }
d2237 2
a2238 2
<FLOAT_VAL>. {
	  errmsg = "A floating-point value was expected";
d2242 1
a2242 1
<STRING_VAL>{STRING} {
d2248 5
a2252 1
	  } else {
d2254 1
d2256 1
a2256 1
	      wptr = (void *)((char *)wcsp + voff);
d2258 50
a2307 10
	      /* Apply keyword parameterization. */
	      if (ptype == 's') {
	        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);
d2309 3
a2311 2
	      } else if (i) {
	        wptr = *((char (**)[72])wptr) + (i - 1);
d2313 1
d2315 7
a2321 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];
d2324 1
a2324 6
	        if (cptr[jx] == '\0') {
	          if (ix) cptr[ix-1] = '\0';
	          break;
	        } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
	          jx++;
	        }
d2326 3
a2328 1
	        ix++;
d2330 3
d2335 2
a2336 1
	    BEGIN(COMMENT);
d2340 7
a2346 2
<STRING_VAL>. {
	  errmsg = "A string value was expected";
d2350 3
a2352 3
<COMMENT>" "*\/.* |
<COMMENT>" "* {
	  BEGIN(FLUSH);
d2355 2
a2356 2
<COMMENT>. {
	  errmsg = "Malformed keycomment";
d2360 1
a2360 1
<DISCARD>.* {
d2364 1
a2364 4
	      if (hptr < wcsbth_hdr-80) {
	        strncpy(hptr, wcsbth_hdr-80, 80);
	      }
	      hptr += 80;
d2366 4
a2369 2
	    } else if (ctrl > 2) {
	      wcsfprintf(stderr, "%.80s\n  Discarded.\n", wcsbth_hdr-80);
a2371 1
	
d2375 1
a2375 2
<ERROR>.* {
	  (*nreject)++;
d2377 4
a2380 6
	    if (ctrl == -1) {
	      if (hptr < wcsbth_hdr-80) {
	        /* Preserve rejects. */
	        strncpy(hptr, wcsbth_hdr-80, 80);
	      }
	      hptr += 80;
d2383 3
a2385 3
	    if (abs(ctrl) > 1) {
	      wcsfprintf(stderr, "%.80s\n%4d: %s.\n", wcsbth_hdr-80, *nreject,
	        errmsg);
a2387 1
	
d2392 7
d2405 2
d2410 1
d2412 2
a2413 2
	  altlin = 0;
	  ptype  = ' ';
d2415 1
d2422 2
a2423 1
	    if ((status = wcsbth_init1(&alts, nwcs, wcs)) || *nwcs == 0) {
d2428 1
a2428 3
	    if (alts.imgherit) npass = 3;
	
	    if (abs(ctrl) > 2) {
d2430 3
a2432 1
	        wcsfprintf(stderr, "Found one coordinate representation.\n");
d2438 2
d2445 1
d2469 10
a2478 2
	      wcsfprintf(stderr, "%d WCS keyrecords were rejected.\n",
	        *nreject);
d2721 1
a2721 1
      } else {
d2748 1
a2748 1
        if (alts->arridx[icol][ialt]) {
d2905 1
a2905 1
* Interpret EPOCH keywords.
d2908 1
a2908 1
int wcsbth_epoch(void *wptr)
a2910 2
  double *equinox;

a2911 1
  equinox = (double *)wptr;
d2913 1
a2913 1
    wcsutil_str2double(yytext, "%lf", equinox);
d2921 1
a2921 1
* Interpret VSOURCE keywords.
d2924 1
a2924 1
int wcsbth_vsource(void *wptr)
d2927 1
a2927 1
  double beta, c = 299792458.0, vsource, *zsource;
a2929 1
  zsource = (double *)wptr;
a2930 2
    wcsutil_str2double(yytext, "%lf", &vsource);

@


4.25.1.1
log
@WCSLIB 4.25 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.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: wcsbth.l,v 4.25.1.2 2015/01/06 01:01:06 mcalabre Exp mcalabre $
d79 1
a79 5
Z1	[0-9]
Z2	[0-9]{2}
Z3	[0-9]{3}
Z4	[0-9]{4}

d90 1
a90 1
FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eEdD][+-]?[0-9]+)?
a92 3
/* Inline comment syntax. */
INLINE " "*(\/.*)?

d156 3
a158 3
  sprintf(strtmp, "%s ", yytext); \
  itmp = strlen(strtmp); \
  while (itmp) unput(strtmp[--itmp]);
d191 2
a192 2
int wcsbth_epoch(double *wptr, double epoch);
int wcsbth_vsource(double *wptr, double vsource);
d203 4
a206 5
	char *cptr, *errmsg, errtxt[80], exclude[1000], gotone, *hptr, *keep,
	     *keyname, *keyrec, ptype, strtmp[80];
	int  altlin, ialt, icol, incl, inttmp, ipass, ipx, itmp, ix, jx,
	     keytype, nother, nsel, npass, nvalid, status, valtype, voff;
	double dbltmp;
d210 1
a210 1
	int (*special)(double *, double);
a221 1
	keyrec = header;
a222 3
	keep = 0x0;
	
	/* For keeping tallies of keywords found. */
a223 5
	nvalid = 0;
	nother = 0;
	
	/* If strict, then also reject. */
	if (relax & WCSHDR_strict) relax |= WCSHDR_reject;
d250 2
a251 2
	altlin  = 0;
	ptype   = ' ';
d298 1
a298 1
	      errmsg = "duplicate or out-of-sequence TFIELDS keyword";
d308 3
a310 1
	  if (!(keysel & IMGAXIS)) {
d316 4
a319 1
	      sscanf(yytext, "WCSAXES%c= %d", &a, &i);
d321 1
a321 12
	      if (i < 0) {
	        errmsg = "negative value of WCSAXESa ignored";
	        BEGIN(ERROR);
	
	      } else {
	        valtype = INTEGER;
	        vptr    = 0x0;
	
	        keyname = "WCSAXESa";
	        keytype = IMGAXIS;
	        BEGIN(COMMENT);
	      }
d324 1
a324 1
	      errmsg = "image-header keyword WCSAXESa in binary table";
d337 1
a337 1
	  keyname = "WCAXna";
d343 1
a343 1
	  if (!(keysel & BIMGARR) || exclude[n]) {
a345 5
	
	  } else if (i < 0) {
	    errmsg = "negative value of WCSAXESa ignored";
	    BEGIN(ERROR);
	
d347 4
a350 6
	    valtype = INTEGER;
	    vptr    = 0x0;
	
	    keyname = "WCAXna";
	    keytype = IMGAXIS;
	    BEGIN(COMMENT);
d358 2
a359 2
	  keyname = "WCSTna";
	  errmsg = "cross-references are not implemented";
d367 2
a368 2
	  keyname = "WCSXna";
	  errmsg = "cross-references are not implemented";
d374 3
a376 3
	  vptr    = &(wcstem.crpix);

	  keyname = "CRPIXja";
d383 1
a383 1
	  vptr    = &(wcstem.crpix);
a387 1
	    keyname = "jCRPna";
d390 1
a390 1
	    keyname = "jCRPXn";
d398 1
a398 1
	  vptr    = &(wcstem.crpix);
a400 1
	    keyname = "TCRPna";
d403 1
a403 1
	    keyname = "TCRPXn";
d410 1
a410 1
	  vptr    = &(wcstem.pc);
d413 1
a413 1
	  keyname = "PCi_ja";
d419 2
a420 2
	  vptr    = &(wcstem.pc);
	  altlin  = 1;
a423 1
	  keyname = "ijPCna";
d430 2
a431 2
	  vptr    = &(wcstem.pc);
	  altlin  = 1;
a433 1
	    keyname = "TPn_ka";
d436 1
a436 1
	    keyname = "TPCn_ka";
d443 2
a444 2
	  vptr    = &(wcstem.cd);
	  altlin  = 2;
d446 1
a446 1
	  keyname = "CDi_ja";
d452 2
a453 2
	  vptr    = &(wcstem.cd);
	  altlin  = 2;
a456 1
	  keyname = "ijCDna";
d463 2
a464 2
	  vptr    = &(wcstem.cd);
	  altlin  = 2;
a466 1
	    keyname = "TCn_ka";
d469 1
a469 1
	    keyname = "TCDn_ka";
d476 1
a476 1
	  vptr    = &(wcstem.cdelt);
d478 1
a478 1
	  keyname = "CDELTia";
d485 1
a485 1
	  vptr    = &(wcstem.cdelt);
a489 1
	    keyname = "iCDEna";
d492 1
a492 1
	    keyname = "iCDLTn";
d500 1
a500 1
	  vptr    = &(wcstem.cdelt);
a502 1
	    keyname = "TCDEna";
d505 1
a505 1
	    keyname = "TCDLTn";
d512 2
a513 2
	  vptr    = &(wcstem.crota);
	  altlin  = 4;
d515 1
a515 1
	  keyname = "CROTAi";
d521 2
a522 2
	  vptr    = &(wcstem.crota);
	  altlin  = 4;
d526 1
a526 1
	  keyname = "iCROTn";
d532 2
a533 2
	  vptr    = &(wcstem.crota);
	  altlin  = 4;
d535 1
a535 1
	  keyname = "TCROTn";
d541 1
a541 1
	  vptr    = &(wcstem.cunit);
d543 1
a543 1
	  keyname = "CUNITia";
d550 1
a550 1
	  vptr    = &(wcstem.cunit);
a554 1
	    keyname = "iCUNna";
d557 1
a557 1
	    keyname = "iCUNIn";
d565 1
a565 1
	  vptr    = &(wcstem.cunit);
a567 1
	    keyname = "TCUNna";
d570 1
a570 1
	    keyname = "TCUNIn";
d577 1
a577 1
	  vptr    = &(wcstem.ctype);
d579 1
a579 1
	  keyname = "CTYPEia";
d586 1
a586 1
	  vptr    = &(wcstem.ctype);
a590 1
	    keyname = "iCTYna";
d593 1
a593 1
	    keyname = "iCTYPn";
d601 1
a601 1
	  vptr    = &(wcstem.ctype);
a603 1
	    keyname = "TCTYna";
d606 1
a606 1
	    keyname = "TCTYPn";
d613 1
a613 1
	  vptr    = &(wcstem.crval);
d615 1
a615 1
	  keyname = "CRVALia";
d622 1
a622 1
	  vptr    = &(wcstem.crval);
a626 1
	    keyname = "iCRVna";
d629 1
a629 1
	    keyname = "iCRVLn";
d637 1
a637 1
	  vptr    = &(wcstem.crval);
a639 1
	    keyname = "TCRVna";
d642 1
a642 1
	    keyname = "TCRVLn";
d650 1
a650 1
	  vptr    = &(wcstem.lonpole);
d653 1
a653 1
	    keyname = "LONPOLEa";
a655 1
	    keyname = "LONPna";
d663 1
a663 1
	  vptr    = &(wcstem.latpole);
d666 1
a666 1
	    keyname = "LATPOLEa";
a668 1
	    keyname = "LATPna";
d673 1
a674 1
^RESTFRQ  |
d677 1
a677 1
	  vptr    = &(wcstem.restfrq);
d680 3
a682 11
	    if (relax & WCSHDR_strict) {
	      errmsg = "the RESTFREQ keyword is deprecated, use RESTFRQa";
	      BEGIN(ERROR);
	
	    } else {
	      unput(' ');
	
	      keyname = "RESTFREQ";
	      BEGIN(CCCCCCCa);
	    }
	
d684 1
a684 1
	    keyname = "RESTFRQa";
a685 1
	
a686 1
	    keyname = "RFRQna";
d694 1
a694 1
	  vptr    = &(wcstem.restwav);
d697 1
a697 1
	    keyname = "RESTWAVa";
a699 1
	    keyname = "RWAVna";
d706 2
a707 2
	  vptr    = &(wcstem.pv);
	  ptype   = 'v';
d709 1
a709 1
	  keyname = "PVi_ma";
d716 2
a717 2
	  vptr    = &(wcstem.pv);
	  ptype   = 'v';
a721 1
	    keyname = "iVn_ma";
d724 1
a724 1
	    keyname = "iPVn_ma";
d732 2
a733 2
	  vptr    = &(wcstem.pv);
	  ptype   = 'v';
a735 1
	    keyname = "TVn_ma";
d738 1
a738 1
	    keyname = "TPVn_ma";
d745 2
a746 2
	  vptr    = &(wcstem.pv);
	  ptype   = 'v';
a747 1
	  keyname = "PROJPm";
d753 2
a754 2
	  vptr    = &(wcstem.ps);
	  ptype   = 's';
d756 1
a756 1
	  keyname = "PSi_ma";
d763 2
a764 2
	  vptr    = &(wcstem.ps);
	  ptype   = 's';
a768 1
	    keyname = "iSn_ma";
d771 1
a771 1
	    keyname = "iPSn_ma";
d779 2
a780 2
	  vptr    = &(wcstem.ps);
	  ptype   = 's';
a782 1
	    keyname = "TSn_ma";
d785 1
a785 1
	    keyname = "TPSn_ma";
d792 1
a792 1
	  vptr    = &(wcstem.cname);
d794 1
a794 1
	  keyname = "CNAMEia";
d801 1
a801 1
	  vptr    = &(wcstem.cname);
a805 1
	    keyname = "iCNAna";
d809 1
a809 1
	    keyname = "iCNAMn";
d817 1
a817 1
	  vptr    = &(wcstem.cname);
a819 1
	    keyname = "TCNAna";
d823 1
a823 1
	    keyname = "TCNAMn";
d830 1
a830 1
	  vptr    = &(wcstem.crder);
d832 1
a832 1
	  keyname = "CRDERia";
d839 1
a839 1
	  vptr    = &(wcstem.crder);
a843 1
	    keyname = "iCRDna";
d847 1
a847 1
	    keyname = "iCRDEn";
d855 1
a855 1
	  vptr    = &(wcstem.crder);
a857 1
	    keyname = "TCRDna";
d861 1
a861 1
	    keyname = "TCRDEn";
d868 1
a868 1
	  vptr    = &(wcstem.csyer);
d870 1
a870 1
	  keyname = "CSYERia";
d877 1
a877 1
	  vptr    = &(wcstem.csyer);
a881 1
	    keyname = "iCSYna";
d885 1
a885 1
	    keyname = "iCSYEn";
d893 1
a893 1
	  vptr    = &(wcstem.csyer);
a895 1
	    keyname = "TCSYna";
d899 1
a899 1
	    keyname = "TCSYEn";
d907 1
a907 1
	  vptr    = wcstem.dateavg;
d910 1
a910 2
	    if (ctrl < -10) keep = keyrec;
	    keyname = "DATE-AVG";
a912 1
	    keyname = "DAVGna";
d919 1
a919 3
	  vptr    = wcstem.dateobs;
	
	  if (ctrl < -10) keep = keyrec;
d921 1
a921 1
	  keyname = "DATE-OBS";
d928 3
a930 2
	  valtype = STRING;
	  vptr    = wcstem.dateobs;
a931 1
	  if (relax & WCSHDR_DOBSn) {
a932 2
	
	    keyname = "DOBSna";
a934 4
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "DOBSna keyword is non-standard";
	    BEGIN(ERROR);
	
d936 7
a942 1
	    BEGIN(DISCARD);
d949 1
a949 5
	  if (relax & WCSHDR_strict) {
	    errmsg = "the EPOCH keyword is deprecated, use EQUINOXa";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || (relax & WCSHDR_EPOCHa)) {
d951 1
a951 1
	    vptr    = &(wcstem.equinox);
d955 1
a955 2
	
	    keyname = "EPOCH";
a957 4
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "EPOCH keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
d959 7
a965 1
	    BEGIN(DISCARD);
d972 1
a972 1
	  vptr    = &(wcstem.equinox);
d975 1
a975 1
	    keyname = "EQUINOXa";
a977 1
	    keyname = "EQUIna";
d985 1
a985 1
	  vptr    = &(wcstem.mjdavg);
d988 1
a988 2
	    if (ctrl < -10) keep = keyrec;
	    keyname = "MJD-AVG";
a990 1
	    keyname = "MJDAn";
d998 1
a998 1
	  vptr    = &(wcstem.mjdobs);
d1001 1
a1001 2
	    if (ctrl < -10) keep = keyrec;
	    keyname = "MJD-OBS";
a1003 1
	    keyname = "MJDOn";
d1011 1
a1011 1
	  vptr    = wcstem.obsgeo;
d1014 1
a1014 2
	    if (ctrl < -10) keep = keyrec;
	    keyname = "OBSGEO-X";
a1016 1
	    keyname = "OBSGXn";
d1024 1
a1024 1
	  vptr    = wcstem.obsgeo + 1;
d1027 1
a1027 2
	    if (ctrl < -10) keep = keyrec;
	    keyname = "OBSGEO-Y";
a1029 1
	    keyname = "OBSGYn";
d1037 1
a1037 1
	  vptr    = wcstem.obsgeo + 2;
d1040 1
a1040 2
	    if (ctrl < -10) keep = keyrec;
	    keyname = "OBSGEO-Z";
a1042 1
	    keyname = "OBSGZn";
d1050 1
a1050 1
	  vptr    = wcstem.radesys;
d1053 1
a1053 1
	    keyname = "RADESYSa";
a1055 1
	    keyname = "RADEna";
d1063 1
a1063 1
	    vptr    = wcstem.radesys;
d1066 1
a1066 2
	
	    keyname = "RADECSYS";
a1068 4
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the RADECSYS keyword is deprecated, use RADESYSa";
	    BEGIN(ERROR);

d1070 7
a1076 1
	    BEGIN(DISCARD);
d1083 1
a1083 1
	  vptr    = wcstem.specsys;
d1086 1
a1086 1
	    keyname = "SPECSYSa";
a1088 1
	    keyname = "SPECna";
d1096 1
a1096 1
	  vptr    = wcstem.ssysobs;
d1099 1
a1099 1
	    keyname = "SSYSOBSa";
a1101 1
	    keyname = "SOBSna";
d1109 1
a1109 1
	  vptr    = wcstem.ssyssrc;
d1112 1
a1112 1
	    keyname = "SSYSSRCa";
a1114 1
	    keyname = "SSRCna";
d1119 2
a1120 2
^VELANGL |
^VANG	{
d1122 1
a1122 1
	  vptr    = &(wcstem.velangl);
d1125 1
a1125 1
	    keyname = "VELANGLa";
a1127 1
	    keyname = "VANGna";
d1132 2
a1133 2
^VELOSYS |
^VSYS	{
d1135 1
a1135 1
	  vptr    = &(wcstem.velosys);
d1138 1
a1138 1
	    keyname = "VELOSYSa";
a1140 1
	    keyname = "VSYSna";
d1148 1
a1148 5
	  if (relax & WCSHDR_strict) {
	    errmsg = "the VELREF keyword is deprecated, use SPECSYSa";
	    BEGIN(ERROR);
	
	  } else if (a == ' ' || (relax & WCSHDR_VELREFa)) {
d1150 1
a1150 1
	    vptr    = &(wcstem.velref);
d1153 1
a1153 2
	
	    keyname = "VELREF";
a1155 4
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VELREF keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
d1157 7
a1163 1
	    BEGIN(DISCARD);
d1170 1
a1170 1
	    vptr    = &(wcstem.zsource);
d1174 1
a1174 2
	
	    keyname = "VSOURCEa";
a1176 4
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "the VSOURCEa keyword is deprecated, use ZSOURCEa";
	    BEGIN(ERROR);
	
d1178 7
a1184 1
	    BEGIN(DISCARD);
d1193 1
a1193 1
	    vptr    = &(wcstem.zsource);
a1196 1
	    keyname = "VSOUna";
a1198 4
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VSOUna keyword is deprecated, use ZSOUna";
	    BEGIN(ERROR);
	
d1200 8
a1207 2
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
d1215 1
a1215 1
	  vptr    = wcstem.wcsname;
d1218 1
a1218 1
	    keyname = "WCSNAMEa";
a1219 1
	
a1220 5
	    if (*yytext == 'W') {
	      keyname = "WCSNna";
	    } else {
	      keyname = "TWCSna";
	    }
d1228 1
a1228 1
	  vptr    = &(wcstem.zsource);
d1231 1
a1231 1
	    keyname = "ZSOURCEa";
a1233 1
	    keyname = "ZSOUna";
d1239 1
d1242 1
a1242 1
	    errmsg = "keyrecords following the END keyrecord were ignored";
d1250 1
d1256 2
a1259 1
	    keytype = IMGAXIS;
d1265 1
a1265 1
	      "image-header keyword %s in binary table", keyname);
d1274 3
a1276 2
<CCCCCia>0{I1}{ALT} |
<CCCCCia>00{I1} {
d1278 3
a1280 51
	    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);
	    }
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "invalid image-header keyword %s in binary table", keyname);
	    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. */
	  if (relax & WCSHDR_ALLIMG) {
	    errmsg = "axis number must exceed 0";
	    BEGIN(ERROR);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "invalid image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<CCCCCia>. {
	  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);
a1296 6
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg, "%s keyword is non-standard", keyname);
	    BEGIN(ERROR);
	
d1298 8
a1305 1
	    BEGIN(DISCARD);
d1317 12
a1328 4
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    if (!vptr) {
	      sprintf(errmsg, "%s keyword is non-standard", keyname);
d1330 2
a1331 2
	      sprintf(errmsg,
	        "%s keyword may not have an alternate version code", keyname);
a1332 5
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
d1362 1
d1371 1
a1371 1
	      "image-header keyword %s in binary table", keyname);
d1380 7
a1386 21
<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} {
d1388 4
a1391 49
	    if (((altlin == 1) && (relax & WCSHDR_PC0i_0ja)) ||
	        ((altlin == 2) && (relax & WCSHDR_CD0i_0ja))) {
	      sscanf(yytext, "%d_%d%c", &i, &j, &a);
	      keytype = IMGAXIS;
	      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);
	    }
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "invalid image-header keyword %s in binary table", keyname);
	    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. */
	  if (relax & WCSHDR_ALLIMG) {
	    errmsg = "axis number must exceed 0";
	    BEGIN(ERROR);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "invalid image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
d1399 1
a1399 29
<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} {
	  if (relax & WCSHDR_ALLIMG) {
	    errmsg = errtxt;
	    sprintf(errmsg, "%s keyword must use an underscore, not a dash",
	      keyname);
	    BEGIN(ERROR);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "invalid image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<CCi_ja>{Z1}{6} {
d1401 6
a1406 19
	  if (relax & WCSHDR_ALLIMG) {
	    if (((altlin == 1) && (relax & WCSHDR_PC00i00j)) ||
	        ((altlin == 2) && (relax & WCSHDR_CD00i00j))) {
	      sscanf(yytext, "%3d%3d", &i, &j);
	      a = ' ';
	      keytype = IMGAXIS;
	      BEGIN(VALUE);
	
	    } else if (relax & WCSHDR_reject) {
	      errmsg = errtxt;
	      sprintf(errmsg,
	        "this form of the %s keyword is deprecated, use %s",
	        keyname, keyname);
	      BEGIN(ERROR);
	
	    } else {
	      /* Pretend we don't recognize it. */
	      BEGIN(DISCARD);
	    }
d1410 2
a1411 2
	    sprintf(errmsg,
	      "deprecated image-header keyword %s in binary table", keyname);
d1444 1
a1444 1
	    sprintf(errmsg, "%s keyword is non-standard", keyname);
d1486 11
a1496 23
<CROTAi>{Z1}{ALT}" " |
<CROTAi>{Z2}{ALT} |
<CROTAi>{Z3} {
	  if (relax & WCSHDR_ALLIMG) {
	    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);
	    }
d1499 1
a1499 3
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "deprecated image-header keyword %s in binary table", keyname);
d1509 1
a1509 7
	  if (relax & WCSHDR_ALLIMG) {
	    yyless(0);
	    BEGIN(CCCCCia);
	  } else {
	    /* Let it go. */
	    BEGIN(DISCARD);
	  }
d1533 1
a1533 1
	      "%s keyword may not have an alternate version code", keyname);
d1563 1
a1563 1
	      "image-header keyword %s in binary table", keyname);
d1573 1
a1573 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);
	  }
d1616 1
a1616 1
<CCi_ma>{I1}_{Z1}{ALT}"  " |
d1618 1
a1618 1
<CCi_ma>{I2}_{Z1}{ALT}" " |
d1629 1
a1629 1
	      "image-header keyword %s in binary table", keyname);
d1638 7
a1644 21
<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} {
d1646 4
a1649 21
	    if (((valtype == FLOAT)  && (relax & WCSHDR_PV0i_0ma)) ||
	        ((valtype == STRING) && (relax & WCSHDR_PS0i_0ma))) {
	      sscanf(yytext, "%d_%d%c", &i, &m, &a);
	      keytype = IMGAXIS;
	      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);
	    }
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "invalid image-header keyword %s in binary table", keyname);
	    BEGIN(ERROR);
a1656 44
<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} {
	  if (relax & WCSHDR_ALLIMG) {
	    /* Anything that has fallen through to this point must contain */
	    /* an invalid parameter. */
	    errmsg = "axis number must exceed 0";
	    BEGIN(ERROR);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "invalid image-header keyword %s in binary table", keyname);
	    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} {
	  errmsg = errtxt;
	  sprintf(errmsg, "%s keyword must use an underscore, not a dash",
	    keyname);
	  BEGIN(ERROR);
	}

d1661 1
a1661 1
<iCCn_ma>{I1}_{Z1}{ALT}" " |
d1664 1
a1664 1
<iCCn_ma>{I2}_{Z1}{ALT}    |
d1666 2
a1667 2
<iCCn_ma>{I3}_{Z1}         |
<TCCn_ma>{I1}_{Z1}{ALT}" " |
d1670 1
a1670 1
<TCCn_ma>{I2}_{Z1}{ALT}    |
d1672 1
a1672 1
<TCCn_ma>{I3}_{Z1} {
d1679 1
a1679 1
	    sprintf(errmsg, "the %s keyword is non-standard", keyname);
d1693 1
a1693 1
<iCn_ma>{I1}_{Z1}{ALT}"  " |
d1696 1
a1696 1
<iCn_ma>{I2}_{Z1}{ALT}" "  |
d1698 2
a1699 2
<iCn_ma>{I3}_{Z1}{ALT}     |
<TCn_ma>{I1}_{Z1}{ALT}"  " |
d1702 1
a1702 1
<TCn_ma>{I2}_{Z1}{ALT}" "  |
d1704 1
a1704 1
<TCn_ma>{I3}_{Z1}{ALT} {
d1714 1
a1714 1
<iCn_ma>{I4}_{Z1} |
d1718 1
a1718 1
<TCn_ma>{I4}_{Z1} {
d1732 1
a1732 1
<PROJPm>{Z1}"  " {
d1741 1
a1741 1
	    errmsg = "the PROJPn keyword is deprecated, use PVi_ma";
a1749 11
<PROJPm>{Z2}" " |
<PROJPm>{Z3} {
	  if (relax & (WCSHDR_PROJPn | WCSHDR_reject)) {
	    errmsg = "invalid PROJPn keyword";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

d1776 1
a1776 1
	        sprintf(errmsg, "axis number exceeds 99");
d1778 1
a1778 1
	        sprintf(errmsg, "parameter number exceeds 99");
d1780 1
a1780 1
	        sprintf(errmsg, "column number exceeds 999");
d1793 8
a1800 6
	  } else {
	    if (ipass == 3 && (keytype & IMGHEAD)) {
	      /* IMGHEAD keytypes are always dealt with on the second pass. */
	      /* However, they must be re-parsed in order to report errors. */
	      vptr = 0x0;
	    }
d1810 1
a1810 1
	      sprintf(errmsg, "internal parser ERROR, bad data type: %d",
d1814 4
d1822 1
a1822 1
	  errmsg = "invalid KEYWORD = VALUE syntax";
d1828 3
a1830 1
	    BEGIN(COMMENT);
d1833 11
a1843 2
	    /* Read the keyvalue. */
	    sscanf(yytext, "%d", &inttmp);
d1850 1
a1850 1
	  errmsg = "an integer value was expected";
d1856 3
a1858 1
	    BEGIN(COMMENT);
d1861 3
a1863 2
	    /* Read the keyvalue. */
	    wcsutil_str2double(yytext, "%lf", &dbltmp);
d1865 10
a1874 12
	    BEGIN(COMMENT);
	  }
	}

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

<STRING_VAL>{STRING} {
	  if (ipass == 1) {
	    BEGIN(COMMENT);
d1876 3
a1878 3
	  } else {
	    /* Read the keyvalue. */
	      strcpy(strtmp, yytext+1);
d1880 5
a1884 5
	    /* Squeeze out repeated quotes. */
	    ix = 0;
	    for (jx = 0; jx < 72; jx++) {
	      if (ix < jx) {
	        strtmp[ix] = strtmp[jx];
d1887 4
a1890 5
	      if (strtmp[jx] == '\0') {
	        if (ix) strtmp[ix-1] = '\0';
	        break;
	      } else if (strtmp[jx] == '\'' && strtmp[jx+1] == '\'') {
	        jx++;
a1891 2
	
	      ix++;
d1898 2
a1899 2
<STRING_VAL>. {
	  errmsg = "a string value was expected";
d1903 1
a1903 1
<COMMENT>{INLINE}$ {
d1909 1
a1909 5
	  } else if (*wcs) {
	    /* Store the value now that the keyrecord has been validated. */
	    alts.icol = 0;
	    alts.ialt = 0;
	
a1910 1
	    gotone = 0;
d1912 1
a1912 1
	      gotone = 1;
d1914 10
a1923 50
	      if (vptr) {
	        voff = (char *)vptr - (char *)(&wcstem);
	        wptr = (void *)((char *)wcsp + voff);
	
	        if (valtype == INTEGER) {
	          *((int *)wptr) = inttmp;
	
	        } else if (valtype == FLOAT) {
	          /* Apply keyword parameterization. */
	          if (ptype == 'v') {
	            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 the 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 (ptype == 's') {
	            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);
	          }
d1925 2
a1926 3
	          cptr = (char *)wptr;
	          strcpy(cptr, strtmp);
	        }
a1927 1
	    }
d1929 9
a1937 7
	    if (ipass == npass) {
	      if (gotone) {
	        nvalid++;
	        if (ctrl == 4) {
	          wcsfprintf(stderr,
	            "%.80s\n  Accepted (%d) as a valid WCS keyrecord.\n",
	            keyrec, nvalid);
d1940 6
a1945 1
	        BEGIN(FLUSH);
d1947 1
a1947 3
	      } else {
	        errmsg = "syntactically valid WCS keyrecord has no effect";
	        BEGIN(ERROR);
a1948 3
	
	    } else {
	      BEGIN(FLUSH);
d1951 1
a1951 2
	  } else {
	    BEGIN(FLUSH);
d1955 2
a1956 2
<COMMENT>.*" "*\/.*$ {
	  errmsg = "invalid keyvalue";
d1960 3
a1962 8
<COMMENT>[^ \/\n]*{INLINE}$ {
	  errmsg = "invalid keyvalue";
	  BEGIN(ERROR);
	}

<COMMENT>" "+[^\/\n].*{INLINE}$ {
	  errmsg = "invalid keyvalue or malformed keycomment";
	  BEGIN(ERROR);
d1965 2
a1966 2
<COMMENT>.*$ {
	  errmsg = "malformed keycomment";
d1970 1
a1970 1
<DISCARD>.*$ {
d1974 4
a1977 1
	      keep = keyrec;
d1979 2
a1980 4
	    } else if (2 < ctrl) {
	      nother++;
	      wcsfprintf(stderr, "%.80s\n  Not a recognised WCS keyword.\n",
	        keyrec);
d1983 1
d1987 2
a1988 1
<ERROR>.*$ {
d1990 6
a1995 4
	    (*nreject)++;
	
	    if (ctrl%10 == -1) {
	      keep = keyrec;
d1998 3
a2000 3
	    if (1 < abs(ctrl%10)) {
	      wcsfprintf(stderr, "%.80s\n  Rejected (%d), %s.\n",
	        keyrec, *nreject, errmsg);
d2003 1
a2007 7
	  if (ipass == npass && keep) {
	    if (hptr < keep) {
	      strncpy(hptr, keep, 80);
	    }
	    hptr += 80;
	  }
	
a2013 2
	  keyrec += 80;
	
a2016 1
	  keep    = 0x0;
d2018 2
a2019 2
	  altlin  = 0;
	  ptype   = ' ';
a2020 1
	
d2027 1
a2027 2
	    if ((status = wcsbth_init1(&alts, nwcs, wcs)) ||
	        (*nwcs == 0 && ctrl == 0)) {
d2032 3
a2034 1
	    if (2 < abs(ctrl%10)) {
d2036 1
a2036 3
	        if (strcmp(wcs[0]->wcsname, "DEFAULTS") != 0) {
	          wcsfprintf(stderr, "Found one coordinate representation.\n");
	        }
a2041 2
	
	    if (alts.imgherit) npass = 3;
a2046 1
	    keyrec = header;
d2070 2
a2071 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");
d2314 1
a2314 1
      } else if (alts->arridx[0][ialt] > 0) {
d2341 1
a2341 1
        if (alts->arridx[icol][ialt] > 0) {
d2498 1
a2498 1
* Interpret EPOCHa keywords.
d2501 1
a2501 1
int wcsbth_epoch(double *equinox, double epoch)
d2504 2
d2507 1
d2509 1
a2509 1
    *equinox = epoch;
d2517 1
a2517 1
* Interpret VSOURCEa keywords.
d2520 1
a2520 1
int wcsbth_vsource(double *zsource, double vsource)
d2523 1
a2523 1
  double beta, c = 299792458.0;
d2526 1
d2528 2
@


4.25.1.4
log
@Americanized spelling (for consistency).
@
text
@d25 1
a25 1
  $Id: wcsbth.l,v 4.25.1.3 2015/03/15 08:59:20 mcalabre Exp mcalabre $
d38 1
a38 1
* wcsbth() may be invoked with an option that causes it to recognize the
d1375 1
a1375 1
	      errmsg = "indices in parameterized keywords must not have "
d1547 1
a1547 1
	      errmsg = "indices in parameterized keywords must not have "
d1935 1
a1935 1
	      errmsg = "indices in parameterized keywords must not have "
d2368 1
a2368 1
	      wcsfprintf(stderr, "%.80s\n  Not a recognized WCS keyword.\n",
d2475 1
a2475 1
	      wcsfprintf(stderr, "%5d %s recognized as syntactically valid, "
d2477 1
a2477 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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.l,v 4.16.1.2 2013/01/29 03:41:24 cal103 Exp cal103 $
@


4.17.1.1
log
@WCSLIB 4.17 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 4.15.1.1 2012/09/26 14:27:51 cal103 Exp cal103 $
d115 1
d1980 1
a1980 1
	      fprintf(stderr, "%.80s\n  Discarded.\n", wcsbth_hdr-80);
d1999 1
a1999 1
	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcsbth_hdr-80, *nreject,
d2031 1
a2031 1

d2036 1
a2036 1
	        fprintf(stderr, "Found one coordinate representation.\n");
d2038 1
a2038 1
	        fprintf(stderr, "Found %d coordinate representations.\n",
d2070 2
a2071 1
	      fprintf(stderr, "%d WCS keyrecords were rejected.\n", *nreject);
@


4.16.1.1
log
@WCSLIB 4.16 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.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: wcsbth.l,v 4.16.1.1 2012/11/07 04:45:56 cal103 Exp cal103 $
a114 1
#include "wcsprintf.h"
d1979 1
a1979 1
	      wcsfprintf(stderr, "%.80s\n  Discarded.\n", wcsbth_hdr-80);
d1998 1
a1998 1
	      wcsfprintf(stderr, "%.80s\n%4d: %s.\n", wcsbth_hdr-80, *nreject,
d2030 1
a2030 1
	
d2035 1
a2035 1
	        wcsfprintf(stderr, "Found one coordinate representation.\n");
d2037 1
a2037 1
	        wcsfprintf(stderr, "Found %d coordinate representations.\n",
d2069 1
a2069 2
	      wcsfprintf(stderr, "%d WCS keyrecords were rejected.\n",
	        *nreject);
@


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: wcsbth.l,v 4.14.1.1 2012/07/13 10:04:44 cal103 Exp cal103 $
@


4.15.1.1
log
@WCSLIB 4.15 development branch.
@
text
@d25 1
a25 1
  $Id: wcsbth.l,v 4.15 2012/09/26 14:26:05 cal103 Exp $
@


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: wcsbth.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: wcsbth.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: wcsbth.l,v 4.12.1.1 2012/02/29 07:59:10 cal103 Exp cal103 $
d115 1
d1883 1
a1883 1
	        sscanf(yytext, "%lf", (double *)wptr);
d2507 1
a2507 1
    sscanf(yytext, "%lf", equinox);
d2526 1
a2526 1
    sscanf(yytext, "%lf", &vsource);
@


4.13.1.1
log
@WCSLIB 4.13 development branch.
@
text
@d31 1
a31 1
  $Id: wcsbth.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: wcsbth.l,v 4.13.1.1 2012/03/14 07:40:37 cal103 Exp cal103 $
a120 1
#include "wcsutil.h"
d1888 1
a1888 1
	        wcsutil_str2double(yytext, "%lf", (double *)wptr);
d2512 1
a2512 1
    wcsutil_str2double(yytext, "%lf", equinox);
d2531 1
a2531 1
    wcsutil_str2double(yytext, "%lf", &vsource);
@


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: wcsbth.l,v 4.13.1.2 2012/07/12 15:23:43 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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.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: wcsbth.l,v 4.7.1.2 2011/08/15 03:18:17 cal103 Exp cal103 $
@


4.8.1.1
log
@WCSLIB 4.8 development branch.
@
text
@d31 1
a31 1
  $Id: wcsbth.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: wcsbth.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: wcsbth.l,v 4.6.1.3 2011/01/14 06:33:16 cal103 Exp cal103 $
d1154 1
a1154 1
	    vptr = wcstem.specsys;
@


4.7.1.1
log
@WCSLIB 4.7 development branch.
@
text
@d31 1
a31 1
  $Id: wcsbth.l,v 4.7 2011/02/07 07:03:42 cal103 Exp $
@


4.7.1.2
log
@Bug fix for parsing VELREF, it was writing the value into wcsprm::specsys
rather than wcsprm::velref.
@
text
@d31 1
a31 1
  $Id: wcsbth.l,v 4.7.1.1 2011/02/07 07:04:22 cal103 Exp cal103 $
d1154 1
a1154 1
	    vptr = &(wcstem.velref);
@


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: wcsbth.l,v 4.5.1.2 2010/11/15 06:55:27 cal103 Exp cal103 $
d174 1
a174 1
  int ncol, iax, icol, imgherit;
d209 1
a209 1
	int  altlin, iax, icol, incl, ipass, ipx, itmp, ix, jx, keytype,
d242 4
a245 4
	for (iax = 0; iax < 27; iax++) {
	  alts.pixidx[iax] = 0;
	  alts.pixnpv[iax] = 0;
	  alts.pixnps[iax] = 0;
d1803 1
a1803 1
	    alts.iax  = 0;
a1833 1
	    if (alts.imgherit) npass = 3;
a1861 1
	    if (alts.imgherit) npass = 3;
a1910 1
	    if (alts.imgherit) npass = 3;
d2035 2
d2105 2
a2106 2
* the 27 possible pixel list coordinate representations are associated each
* table column.
d2120 1
a2120 1
  int iax, icol, mask, ncol;
d2145 4
d2165 4
d2174 5
a2178 5
      for (iax = 0; iax < 27; iax++) {
        alts->arridx[icol][iax] = 0;
        alts->npv[icol][iax] = 0;
        alts->nps[icol][iax] = 0;
        alts->pixlist[icol]  = 0;
d2185 1
a2185 1
  iax = 0;
d2187 1
a2187 1
    iax = a - 'A' + 1;
d2195 1
a2195 1
      if (alts->arridx[n][iax] == 0) {
d2197 1
a2197 1
        alts->arridx[n][iax] = -1;
d2202 2
a2203 2
      if (alts->arridx[n][iax] < i) {
        alts->arridx[n][iax] = i;
d2206 2
a2207 2
      if (alts->arridx[n][iax] < j) {
        alts->arridx[n][iax] = j;
d2212 1
a2212 1
      alts->npv[n][iax]++;
d2214 1
a2214 1
      alts->nps[n][iax]++;
d2222 1
a2222 1
    mask = 1 << iax;
d2232 1
a2232 1
      alts->pixnpv[iax]++;
d2234 1
a2234 1
      alts->pixnps[iax]++;
d2255 1
a2255 1
  int iax, icol, inherit[27], ix, mask, ncol, npsmax, npvmax, status = 0;
d2266 2
a2267 2
  for (iax = 0, mask = 1; iax < 27; iax++, mask <<= 1) {
    alts->pixidx[iax] = 0;
d2272 1
a2272 1
          alts->pixidx[iax]++;
d2281 2
a2282 2
  for (iax = 0; iax < 27; iax++) {
    inherit[iax] = 0;
d2285 1
a2285 1
      if (alts->arridx[icol][iax] < 0) {
d2287 1
a2287 1
        if (alts->arridx[0][iax] > 0) {
d2290 1
a2290 1
          alts->arridx[icol][iax] = alts->arridx[0][iax];
d2292 1
a2292 1
          alts->arridx[icol][iax] = 0;
d2296 4
a2299 4
      if (alts->arridx[icol][iax]) {
        if (alts->arridx[0][iax]) {
          /* All IMGHEAD keywords are inherited for this iax. */
          inherit[iax] = 1;
d2301 1
a2301 1
          if (alts->arridx[icol][iax] < alts->arridx[0][iax]) {
d2303 1
a2303 1
            alts->arridx[icol][iax] = alts->arridx[0][iax];
d2312 2
a2313 2
    if (alts->arridx[0][iax]) {
      if (inherit[iax]) {
d2315 1
a2315 1
        alts->arridx[0][iax] = 0;
d2323 1
a2323 1
    if (alts->pixidx[iax]) {
d2343 2
a2344 2
      for (iax = 0; iax < 27; iax++) {
        if (alts->arridx[icol][iax]) {
d2348 3
a2350 3
          wcsnpv(alts->npv[icol][iax]);
          wcsnps(alts->nps[icol][iax]);
          if ((status = wcsini(1, (int)(alts->arridx[icol][iax]), wcsp))) {
d2356 2
a2357 2
          if (iax) {
            wcsp->alt[0] = 'A' + iax - 1;
d2365 1
a2365 1
          alts->arridx[icol][iax] = (*nwcs)++;
d2371 1
a2371 1
          alts->arridx[icol][iax] = -1;
d2376 2
a2377 2
    for (iax = 0; iax < 27; iax++) {
      if (alts->pixidx[iax]) {
d2380 3
a2382 3
        wcsnpv(alts->pixnpv[iax]);
        wcsnps(alts->pixnps[iax]);
        if ((status = wcsini(1, (int)(alts->pixidx[iax]), wcsp))) {
d2388 2
a2389 2
        if (iax) {
          wcsp->alt[0] = 'A' + iax - 1;
d2393 1
a2393 1
        mask = (1 << iax);
d2401 1
a2401 1
        alts->pixidx[iax] = (*nwcs)++;
d2407 1
a2407 1
        alts->pixidx[iax] = -1;
d2439 1
a2439 1
  for (; iwcs < 0 && alts->iax < 27; alts->iax++) {
d2441 2
a2442 2
       loop simply determines the appropriate value of alts->iax. */
    if (a && a != as[alts->iax]) continue;
d2449 1
a2449 1
        iwcs = alts->arridx[alts->icol][alts->iax];
d2452 1
a2452 1
      /* Break out of the loop to stop alts->iax from being incremented. */
d2455 1
a2455 1
      /* Start from scratch for the next alts->iax. */
d2460 1
a2460 1
      iwcs = alts->pixidx[alts->iax];
d2552 6
a2557 1
  int iax, status;
d2559 1
a2559 1
  for (iax = 0; iax < *nwcs; iax++) {
d2561 1
a2561 1
    if ((status = wcstab(*wcs+iax))) {
@


4.6.1.1
log
@WCSLIB 4.6 development branch.
@
text
@d31 1
a31 1
  $Id: wcsbth.l,v 4.6 2010/11/16 06:15:31 cal103 Exp $
@


4.6.1.2
log
@In wcsbth_final(), free alts.  Fixed handling of alts.imgherit.
Renamed iax -> ialt.
@
text
@d31 1
a31 1
  $Id: wcsbth.l,v 4.6.1.1 2010/11/16 06:16:19 cal103 Exp cal103 $
d174 1
a174 1
  int ncol, ialt, icol, imgherit;
d209 1
a209 1
	int  altlin, ialt, icol, incl, ipass, ipx, itmp, ix, jx, keytype,
d242 4
a245 4
	for (ialt = 0; ialt < 27; ialt++) {
	  alts.pixidx[ialt] = 0;
	  alts.pixnpv[ialt] = 0;
	  alts.pixnps[ialt] = 0;
d1803 1
a1803 1
	    alts.ialt = 0;
d1834 1
d1863 1
d1913 1
a2037 2

	    if (alts.imgherit) npass = 3;
d2106 2
a2107 2
* the 27 possible pixel list coordinate representations are associated with
* each table column.
d2121 1
a2121 1
  int ialt, icol, mask, ncol;
a2145 4
      if (alts->arridx)  free(alts->arridx);
      if (alts->npv)     free(alts->npv);
      if (alts->nps)     free(alts->nps);
      if (alts->pixlist) free(alts->pixlist);
a2161 4
      if (alts->arridx)  free(alts->arridx);
      if (alts->npv)     free(alts->npv);
      if (alts->nps)     free(alts->nps);
      if (alts->pixlist) free(alts->pixlist);
d2167 5
a2171 5
      for (ialt = 0; ialt < 27; ialt++) {
        alts->arridx[icol][ialt] = 0;
        alts->npv[icol][ialt] = 0;
        alts->nps[icol][ialt] = 0;
        alts->pixlist[icol]   = 0;
d2178 1
a2178 1
  ialt = 0;
d2180 1
a2180 1
    ialt = a - 'A' + 1;
d2188 1
a2188 1
      if (alts->arridx[n][ialt] == 0) {
d2190 1
a2190 1
        alts->arridx[n][ialt] = -1;
d2195 2
a2196 2
      if (alts->arridx[n][ialt] < i) {
        alts->arridx[n][ialt] = i;
d2199 2
a2200 2
      if (alts->arridx[n][ialt] < j) {
        alts->arridx[n][ialt] = j;
d2205 1
a2205 1
      alts->npv[n][ialt]++;
d2207 1
a2207 1
      alts->nps[n][ialt]++;
d2215 1
a2215 1
    mask = 1 << ialt;
d2225 1
a2225 1
      alts->pixnpv[ialt]++;
d2227 1
a2227 1
      alts->pixnps[ialt]++;
d2248 1
a2248 1
  int ialt, icol, inherit[27], ix, mask, ncol, npsmax, npvmax, status = 0;
d2259 2
a2260 2
  for (ialt = 0, mask = 1; ialt < 27; ialt++, mask <<= 1) {
    alts->pixidx[ialt] = 0;
d2265 1
a2265 1
          alts->pixidx[ialt]++;
d2274 2
a2275 2
  for (ialt = 0; ialt < 27; ialt++) {
    inherit[ialt] = 0;
d2278 1
a2278 1
      if (alts->arridx[icol][ialt] < 0) {
d2280 1
a2280 1
        if (alts->arridx[0][ialt] > 0) {
d2283 1
a2283 1
          alts->arridx[icol][ialt] = alts->arridx[0][ialt];
d2285 1
a2285 1
          alts->arridx[icol][ialt] = 0;
d2289 4
a2292 4
      if (alts->arridx[icol][ialt]) {
        if (alts->arridx[0][ialt]) {
          /* All IMGHEAD keywords are inherited for this ialt. */
          inherit[ialt] = 1;
d2294 1
a2294 1
          if (alts->arridx[icol][ialt] < alts->arridx[0][ialt]) {
d2296 1
a2296 1
            alts->arridx[icol][ialt] = alts->arridx[0][ialt];
d2305 2
a2306 2
    if (alts->arridx[0][ialt]) {
      if (inherit[ialt]) {
d2308 1
a2308 1
        alts->arridx[0][ialt] = 0;
d2316 1
a2316 1
    if (alts->pixidx[ialt]) {
d2336 2
a2337 2
      for (ialt = 0; ialt < 27; ialt++) {
        if (alts->arridx[icol][ialt]) {
d2341 3
a2343 3
          wcsnpv(alts->npv[icol][ialt]);
          wcsnps(alts->nps[icol][ialt]);
          if ((status = wcsini(1, (int)(alts->arridx[icol][ialt]), wcsp))) {
d2349 2
a2350 2
          if (ialt) {
            wcsp->alt[0] = 'A' + ialt - 1;
d2358 1
a2358 1
          alts->arridx[icol][ialt] = (*nwcs)++;
d2364 1
a2364 1
          alts->arridx[icol][ialt] = -1;
d2369 2
a2370 2
    for (ialt = 0; ialt < 27; ialt++) {
      if (alts->pixidx[ialt]) {
d2373 3
a2375 3
        wcsnpv(alts->pixnpv[ialt]);
        wcsnps(alts->pixnps[ialt]);
        if ((status = wcsini(1, (int)(alts->pixidx[ialt]), wcsp))) {
d2381 2
a2382 2
        if (ialt) {
          wcsp->alt[0] = 'A' + ialt - 1;
d2386 1
a2386 1
        mask = (1 << ialt);
d2394 1
a2394 1
        alts->pixidx[ialt] = (*nwcs)++;
d2400 1
a2400 1
        alts->pixidx[ialt] = -1;
d2432 1
a2432 1
  for (; iwcs < 0 && alts->ialt < 27; alts->ialt++) {
d2434 2
a2435 2
       loop simply determines the appropriate value of alts->ialt. */
    if (a && a != as[alts->ialt]) continue;
d2442 1
a2442 1
        iwcs = alts->arridx[alts->icol][alts->ialt];
d2445 1
a2445 1
      /* Break out of the loop to stop alts->ialt from being incremented. */
d2448 1
a2448 1
      /* Start from scratch for the next alts->ialt. */
d2453 1
a2453 1
      iwcs = alts->pixidx[alts->ialt];
d2545 1
a2545 6
  int ialt, status;

  if (alts->arridx)  free(alts->arridx);
  if (alts->npv)     free(alts->npv);
  if (alts->nps)     free(alts->nps);
  if (alts->pixlist) free(alts->pixlist);
d2547 1
a2547 1
  for (ialt = 0; ialt < *nwcs; ialt++) {
d2549 1
a2549 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: wcsbth.l,v 4.6.1.2 2010/11/24 01:25:14 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: wcsbth.l,v 4.4.1.3 2010/07/07 13:32:16 cal103 Exp cal103 $
d73 1
a73 1
* wcsbth() does not currently handle the Greenbank convention.
@


4.5.1.1
log
@WCSLIB 4.5 development branch.
@
text
@d31 1
a31 1
  $Id: wcsbth.l,v 4.5 2010/07/16 07:01:25 cal103 Exp $
@


4.5.1.2
log
@"Greenbank convention" -> "Green Bank convention" in the prologue.
@
text
@d31 1
a31 1
  $Id: wcsbth.l,v 4.5.1.1 2010/07/16 07:05:31 cal103 Exp cal103 $
d73 1
a73 1
* wcsbth() does not currently handle the Green Bank convention.
@


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: wcsbth.l,v 4.3.1.4 2009/07/23 04:51:49 cal103 Exp cal103 $
a195 1
int wcsbth_velref(void *wptr);
a1154 1
	    special = wcsbth_velref;
a2512 26
* Interpret VELREF keywords.
*---------------------------------------------------------------------------*/

int wcsbth_velref(void *wptr)

{
  const char *frames[] = {"LSRK", "BARYCENT", "TOPOCENT",
                          "LSRD", "GEOCENTR", "SOURCE", "GALACTOC"};
  char *specsys;
  int ivf, velref;

  /* If SPECSYSa is currently undefined then set it from VELREF. */
  specsys = (char *)wptr;
  if (specsys[0] == '\0') {
    sscanf(yytext, "%d", &velref);
    ivf = velref%256 - 1;
    if (0 <= ivf && ivf < 7) {
      sprintf(specsys, "%s", frames[ivf]);
    }
  }

  return 0;
}


/*----------------------------------------------------------------------------
@


4.4.1.1
log
@WCSLIB 4.4 development branch.
@
text
@d31 1
a31 1
  $Id: wcsbth.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: wcsbth.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: wcsbth.l,v 4.4.1.2 2010/01/19 03:42:50 cal103 Exp cal103 $
d196 1
d1156 1
d2515 26
@


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: wcsbth.l,v 0.0.1.7 2007/12/27 05:11:41 cal103 Exp cal103 $
d34 4
a37 4
*   wcsbth.l is a Flex description file containing the definition of a lexical
*   scanner for parsing the WCS keyrecords for one or more image arrays and/or
*   pixel lists in a FITS binary table header.  It can also handle primary
*   image and image extension headers.
d39 2
a40 2
*   wcsbth.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a
*   description of the user interface and operating notes.
d42 8
a49 8
*   Implementation notes
*   --------------------
*   wcsbth() may be invoked with an option that causes it to recognise the
*   image-header form of WCS keywords as defaults for each alternate
*   coordinate representation (up to 27).  By design, with this option enabled
*   wcsbth() can also handle primary image and image extension headers,
*   effectively treating them as a single-column binary table though with WCS
*   keywords of a different form.
d51 9
a59 9
*   NAXIS is always 2 for binary tables, it refers to the two-dimensional
*   nature of the table.  Thus NAXIS does not count the number of image axes
*   in either image arrays or pixels lists and for the latter there is not
*   even a formal equivalent of WCSAXESa.  Hence NAXIS is always ignored and a
*   first pass through the header is required to determine the number of
*   images, the number of alternate coordinate representations for each image
*   (up to 27), and the number of coordinate axes in each representation; this
*   pass also counts the number of iPVn_ma and iPSn_ma or TVk_ma and TSk_ma
*   keywords in each representation.
d61 5
a65 5
*   On completion of the first pass, the association between column number
*   and axis number is defined for each representation of a pixel list.
*   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.
d67 2
a68 2
*   It is permissible for a scalar table column to contain degenerate (single-
*   point) image arrays and simultaneously form one axis of a pixel list.
d70 2
a71 2
*   The parser does not check for duplicated keywords, for most keywords it
*   accepts the last encountered.
d73 1
a73 1
*   wcsbth() does not currently handle the Greenbank convention.
d113 1
d131 1
a131 1
                        /* CTYPEia.                                 */
d168 4
d188 1
a188 1
                 struct wcsbth_alts *alts);
d192 1
a192 1
                 int keytype, int n, char a);
d216 1
a216 1
        int yylex_destroy (void);
d288 6
d1174 1
a1174 1
	  if (relax & WCSHDR_VSOURCEa) {
d1197 1
a1197 1
	  if (relax & WCSHDR_VSOURCEa) {
d1218 1
a1218 1
^WCSN |
d1777 1
a1777 1

d2033 1
a2033 1
<<EOF>> {
d2087 1
a2087 1
*   Perform first-pass tasks:
d2089 3
a2091 3
*   1) Count the number of coordinate axes in each of the 27 possible
*      alternate image-header coordinate representations.  Also count the
*      number of PVi_ma and PSi_ma keywords in each representation.
d2093 4
a2096 4
*   2) Determine the number of binary table columns that have an image array
*      with a coordinate representation (up to 999), and count the number of
*      coordinate axes in each of the 27 possible alternates.  Also count the
*      number of iVn_ma and iSn_ma keywords in each representation.
d2098 3
a2100 3
*   3) Determine the number of alternate pixel list coordinate representations
*      (up to 27) and the table columns associated with each.  Also count the
*      number of TVn_ma and TSn_ma keywords in each representation.
d2102 4
a2105 4
*   In the first pass alts->arridx[icol][27] is used to determine the number
*   of axes in each of 27 possible image-header coordinate descriptions
*   (icol == 0) and each of the 27 possible coordinate representations for an
*   image array in each column.
d2107 3
a2109 3
*   The elements of alts->pixlist[icol] are used as bit arrays to flag which
*   of the 27 possible pixel list coordinate representations are associated
*   each table column.
d2238 1
a2238 4
*   Perform initializations at the end of the first pass:
*
*   1) Determine the required number of wcsprm structs, allocate memory for
*      an array of them and initialize each one.
d2240 2
d2284 1
a2284 1
	     representation. */
d2416 2
a2417 2
*   Return a pointer to the next wcsprm struct for a particular column number
*   and alternate.
d2464 2
a2465 2
*   Return the axis number associated with the specified column number in a
*   particular pixel list coordinate representation.
d2496 1
a2496 1
*   Interpret EPOCH keywords.
d2515 1
a2515 1
*   Interpret VELREF keywords.
d2541 1
a2541 1
*   Interpret VSOURCE keywords.
d2556 1
a2556 1
    *zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
d2564 1
a2564 1
*   Tie up loose ends.
@


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: wcsbth.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 wcsbth()
to handle parser errors.
@
text
@d4 1
a4 1
    Copyright (C) 1995-2009, Mark Calabretta
d31 1
a31 1
    $Id: wcsbth.l,v 4.3.1.2 2008/04/02 03:51:53 cal103 Exp cal103 $
d54 2
a55 2
*   even a formal equivalent of WCSAXESa.  Hence NAXIS is always ignored and
*   a first pass through the header is required to determine the number of
a112 1
#include <setjmp.h>
d130 1
a130 1
			/* CTYPEia.                                 */
a166 4
/* Used in preempting the call to exit() by yy_fatal_error(). */
jmp_buf wcsbth_abort_jmp_env;
#define exit(status) longjmp(wcsbth_abort_jmp_env, status)

d183 1
a183 1
        struct wcsbth_alts *alts);
d187 1
a187 1
        int keytype, int n, char a);
d211 1
a211 1
	int yylex_destroy(void);
a282 6
	
	/* Return here via longjmp() invoked by yy_fatal_error(). */
	if (setjmp(wcsbth_abort_jmp_env)) {
	  return 4;
	}
	
d1766 1
a1766 1
	
d2274 1
a2274 1
             representation. */
d2546 1
a2546 1
    *zsource = (1.0 + beta)/sqrt(1.0 - beta*beta) - 1.0;
@


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: wcsbth.l,v 4.3.1.2 2009/04/30 02:42:20 cal103 Exp cal103 $
d34 4
a37 4
* wcsbth.l is a Flex description file containing the definition of a lexical
* scanner for parsing the WCS keyrecords for one or more image arrays and/or
* pixel lists in a FITS binary table header.  It can also handle primary image
* and image extension headers.
d39 2
a40 2
* wcsbth.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
* of the user interface and operating notes.
d42 8
a49 8
* Implementation notes
* --------------------
* wcsbth() may be invoked with an option that causes it to recognise the
* image-header form of WCS keywords as defaults for each alternate coordinate
* representation (up to 27).  By design, with this option enabled wcsbth() can
* also handle primary image and image extension headers, effectively treating
* them as a single-column binary table though with WCS keywords of a different
* form.
d51 9
a59 9
* NAXIS is always 2 for binary tables, it refers to the two-dimensional nature
* of the table.  Thus NAXIS does not count the number of image axes in either
* image arrays or pixels lists and for the latter there is not even a formal
* equivalent of WCSAXESa.  Hence NAXIS is always ignored and a first pass
* through the header is required to determine the number of images, the number
* of alternate coordinate representations for each image (up to 27), and the
* number of coordinate axes in each representation; this pass also counts the
* number of iPVn_ma and iPSn_ma or TVk_ma and TSk_ma keywords in each
* representation.
d61 5
a65 5
* On completion of the first pass, the association between column number and
* axis number is defined for each representation of a pixel list.  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.
d67 2
a68 2
* It is permissible for a scalar table column to contain degenerate (single-
* point) image arrays and simultaneously form one axis of a pixel list.
d70 2
a71 2
* The parser does not check for duplicated keywords, for most keywords it
* accepts the last encountered.
d73 1
a73 1
* wcsbth() does not currently handle the Greenbank convention.
d1218 1
a1218 1
^WCSN	 |
d2033 1
a2033 1
<<EOF>>	 {
d2087 1
a2087 1
* Perform first-pass tasks:
d2089 3
a2091 3
* 1) Count the number of coordinate axes in each of the 27 possible alternate
*    image-header coordinate representations.  Also count the number of PVi_ma
*    and PSi_ma keywords in each representation.
d2093 4
a2096 4
* 2) Determine the number of binary table columns that have an image array
*    with a coordinate representation (up to 999), and count the number of
*    coordinate axes in each of the 27 possible alternates.  Also count the
*    number of iVn_ma and iSn_ma keywords in each representation.
d2098 3
a2100 3
* 3) Determine the number of alternate pixel list coordinate representations
*    (up to 27) and the table columns associated with each.  Also count the
*    number of TVn_ma and TSn_ma keywords in each representation.
d2102 4
a2105 4
* In the first pass alts->arridx[icol][27] is used to determine the number of
* axes in each of 27 possible image-header coordinate descriptions (icol == 0)
* and each of the 27 possible coordinate representations for an image array in
* each column.
d2107 3
a2109 3
* The elements of alts->pixlist[icol] are used as bit arrays to flag which of
* the 27 possible pixel list coordinate representations are associated each
* table column.
d2238 4
a2241 1
* Perform initializations at the end of the first pass:
a2242 2
* 1) Determine the required number of wcsprm structs, allocate memory for
*    an array of them and initialize each one.
d2417 2
a2418 2
* Return a pointer to the next wcsprm struct for a particular column number
* and alternate.
d2465 2
a2466 2
* Return the axis number associated with the specified column number in a
* particular pixel list coordinate representation.
d2497 1
a2497 1
* Interpret EPOCH keywords.
d2516 1
a2516 1
* Interpret VELREF keywords.
d2542 1
a2542 1
* Interpret VSOURCE keywords.
d2565 1
a2565 1
* Tie up loose ends.
@


4.3.1.4
log
@Renamed WCSHDR_VSOURCEa -> WCSHDR_VSOURCE.
@
text
@d31 1
a31 1
  $Id: wcsbth.l,v 4.3.1.3 2009/07/22 04:52:32 cal103 Exp cal103 $
d1174 1
a1174 1
	  if (relax & WCSHDR_VSOURCE) {
d1197 1
a1197 1
	  if (relax & WCSHDR_VSOURCE) {
@


0.0
log
@Empty revision.
@
text
@d1 2574
@


0.0.1.1
log
@Initial revision handles pixel lists only, without attempting to separate
multiple images.
@
text
@a0 1473
/*============================================================================
*
*   WCSLIB 4.3 - an implementation of the FITS WCS standard.
*   Copyright (C) 1995-2007, 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$
*=============================================================================
*
*   wcsbth.l is a Flex description file containing a lexical scanner
*   definition for extracting the WCS cards for a pixel list from a FITS
*   header.
*
*   It requires Flex v2.5.4 or later.
*
*   Refer to wcshdr.h for a description of the user interface and operating
*   notes.
*
*   Pixel lists are implemented as binary tables whence NAXIS = 2, referring
*   to the two-dimensional nature of the table.  Thus NAXIS does not count the
*   number of image axes and formally there is no equivalent for WCSAXESa.
*   Hence the scanner must 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
*   TVk_ma and TSk_ma cards in each representation.
*
*   On completion of the first pass, the association between column number and
*   axis number is defined for each representation.  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 cards, it accepts the last
*   encountered.
*
*===========================================================================*/

/* Options. */
%option full
%option never-interactive
%option noyywrap

/* Indices for parameterized keywords. */
I0	[0-9]
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]+)([eE][+-]?[0-9]+)?
STRING	'([^']|'')*'

/* Exclusive start states. */
%x TCROTn PROJPm
%x CCCCCCCC CCCCCCCa CCCCna CCCCCn CCn_ka CCCn_ka CCn_ma CCCn_ma
%x VALUE INTEGER_VAL FLOAT_VAL STRING_VAL
%x COMMENT DISCARD ERROR FLUSH

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

#include "wcs.h"
#include "wcshdr.h"
#include "wcsmath.h"

#define INTEGER 0
#define FLOAT   1
#define STRING  2

#define YY_DECL int wcsbth(char *header, int ncards, int relax, int ctrl, \
                           int *nreject, int *nwcs, struct wcsprm **wcs)

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

#ifdef DEBUG
  /* Print text as it is matched. */
  #define YY_USER_ACTION printf("Rule %03d: \"%s\"\n", yy_act, yytext);
#endif

/* These global variables are required by YY_INPUT. */
char *wcsbth_hdr;
int  wcsbth_ncards;

void wcsbth_naxes(int n, int k, char a, int alts[], int colalt[], int *npptr);
int  wcsbth_inits(int colalt[], int npv[], int nps[], int *nwcs,
                  struct wcsprm **wcs, int alts[]);
int  wcsbth_colax(struct wcsprm **wcs, int alts[], int k, char a);
int  wcsbth_final(int alts[], double epoch[], int velref[], double vsource[],
                  int *nwcs, struct wcsprm **wcs);

%}

%%
        /* Keyword indices, as used in the WCS papers, e.g. TPn_ka, TVn_ma. */
	char a;
	int  i, j, k, m, n;
	
	char *cptr, errmsg[80], *hptr;
	int  altlin, alts[27], *colalt, iax, idx, ipx, ix, jx, ncols, *npptr,
	     nps[27], npv[27], pass, status, type, velref[27], voff;
	double epoch[27], vsource[27];
	void *vptr, *wptr;
	struct wcsprm *wcsp;
	
	for (iax = 0; iax < 27; iax++) {
	  alts[iax] = 0;
	  npv[iax] = 0;
	  nps[iax] = 0;
	  epoch[iax]   = UNDEFINED;
	  velref[iax]  = 0;
	  vsource[iax] = UNDEFINED;
	}
	
	wcsbth_hdr = header;
	wcsbth_ncards = ncards;
	
	hptr = header;
	*nreject = 0;
	*nwcs = 0;
	*wcs  = 0x0;
	
	pass = 1;
	i = j = k = m = n = 0;
	a = ' ';
	idx  = -1;
	type = -1;
	altlin = 0;
	ncols  = 0;
	colalt = 0x0;
	npptr  = 0x0;
	vptr   = 0x0;
	
	BEGIN(INITIAL);


^TFIELDS" = "" "*{INTEGER} {
	  /* Rule 001. */
	  if (pass == 1) {
	    sscanf(yytext, "TFIELDS = %d", &ncols);
	
	    /* One byte for each column records the alternate version code. */
	    if (!(colalt = calloc(ncols+1, sizeof(int)))) {
	      yy_delete_buffer(YY_CURRENT_BUFFER);
	      return 2;
	    }
	
	    /* calloc() will have zeroed all elements. */
	    colalt[0] = ncols;
	  }
	  BEGIN(FLUSH);
	}

^WCSNAME |
^TWCS {
	  /* Rules 002-003. */
	  if (*wcs) vptr = (*wcs)->wcsname;
	  type = STRING;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^TCRPX	|
^TCRP	{
	  /* Rules 004-005. */
	  if (*wcs) vptr = &((*wcs)->crpix);
	  type = FLOAT;
	  if (yyleng == 5) {
	    BEGIN(CCCCCn);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^TPC	|
^TP	{
	  /* Rules 006-007. */
	  if (*wcs) {
	    vptr = &((*wcs)->pc);
	    altlin = 1;
	  }
	  type = FLOAT;
	
	  if (yyleng == 3) {
	    if (relax & (WCSHDR_all | WCSHDR_LONGKEY)) {
	      BEGIN(CCCn_ka);
	    } else if (relax & WCSHDR_reject) {
	      sprintf(errmsg, "Non-standard TPCn_ka keyword rejected");
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  } else {
	    BEGIN(CCn_ka);
	  }
	}

^TCD	|
^TC	{
	  /* Rules 008-009. */
	  if (*wcs) {
	    vptr = &((*wcs)->cd);
	    altlin = 2;
	  }
	  type = FLOAT;
	
	  if (yyleng == 3) {
	    if (relax & (WCSHDR_all | WCSHDR_LONGKEY)) {
	      BEGIN(CCCn_ka);
	    } else if (relax & WCSHDR_reject) {
	      sprintf(errmsg, "Non-standard TCDn_ka keyword rejected");
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  } else {
	    BEGIN(CCn_ka);
	  }
	}

^TCDLT	|
^TCDE	{
	  /* Rules 010-011. */
	  if (*wcs) vptr = &((*wcs)->cdelt);
	  type = FLOAT;
	  if (yyleng == 5) {
	    BEGIN(CCCCCn);
	  } else {
	    BEGIN(CCCCna);
	  }
	}


^TCROT	{
	  /* Rule 012. */
	  if (*wcs) {
	    vptr = &((*wcs)->crota);
	    altlin = 4;
	  }
	  type = FLOAT;
	  BEGIN(TCROTn);
	}

^TCUNI	|
^TCUN	{
	  /* Rules 013-014. */
	  if (*wcs) vptr = &((*wcs)->cunit);
	  type = STRING;
	  if (yyleng == 5) {
	    BEGIN(CCCCCn);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^TCTYP	|
^TCTY	{
	  /* Rules 015-016. */
	  if (*wcs) vptr = &((*wcs)->ctype);
	  type = STRING;
	  if (yyleng == 5) {
	    BEGIN(CCCCCn);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^TCRVL	|
^TCRV	{
	  /* Rules 017-018. */
	  if (*wcs) vptr = &((*wcs)->crval);
	  type = FLOAT;
	  if (yyleng == 5) {
	    BEGIN(CCCCCn);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^TCNAM	|
^TCNA	{
	  /* Rules 019-020. */
	  if (*wcs) vptr = &((*wcs)->cname);
	  type = STRING;
	  if (yyleng == 5) {
	    BEGIN(CCCCCn);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^TCRDE	|
^TCRD	{
	  /* Rules 021-022. */
	  if (*wcs) vptr = &((*wcs)->crder);
	  type = FLOAT;
	  if (yyleng == 5) {
	    BEGIN(CCCCCn);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^TCSYE	|
^TCSY	{
	  /* Rules 023-024. */
	  if (*wcs) vptr = &((*wcs)->csyer);
	  type = FLOAT;
	  if (yyleng == 5) {
	    BEGIN(CCCCCn);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^TPV	|
^TV	{
	  /* Rules 025-026. */
	  npptr = npv;
	  if (*wcs) vptr = &((*wcs)->pv);
	  type = FLOAT;
	  if (yyleng == 3) {
	    if (relax & (WCSHDR_all | WCSHDR_LONGKEY)) {
	      BEGIN(CCCn_ma);
	    } else if (relax & WCSHDR_reject) {
	      sprintf(errmsg, "Non-standard TPVn_ma keyword rejected");
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  } else {
	    BEGIN(CCn_ma);
	  }
	}

^PROJP	{
	  /* Rule 027. */
	  npptr = npv;
	  if (*wcs) vptr = &((*wcs)->pv);
	  type = FLOAT;
	  BEGIN(PROJPm);
	}

^TPS	|
^TS	{
	  /* Rules 028-029. */
	  npptr = nps;
	  if (*wcs) vptr = &((*wcs)->ps);
	  type = STRING;
	  if (yyleng == 3) {
	    if (relax & (WCSHDR_all | WCSHDR_LONGKEY)) {
	      BEGIN(CCCn_ma);
	    } else if (relax & WCSHDR_reject) {
	      sprintf(errmsg, "Non-standard TPSn_ma keyword rejected");
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  } else {
	    BEGIN(CCn_ma);
	  }
	}

^LONPOLE |
^LONP	{
	  /* Rules 030-031. */
	  if (*wcs) vptr = &((*wcs)->lonpole);
	  type = FLOAT;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^LATPOLE |
^LATP	{
	  /* Rules 032-033. */
	  if (*wcs) vptr = &((*wcs)->latpole);
	  type = FLOAT;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^RADECSYS {
	  /* Rule 034. */
	  unput(' ');
	  if (*wcs) vptr = (*wcs)->radesys;
	  type = STRING;
	  BEGIN(CCCCCCCa);
	}

^RADESYS |
^RADE	{
	  /* Rules 035-036. */
	  if (*wcs) vptr = (*wcs)->radesys;
	  type = STRING;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^EQUINOX |
^EQUI	 {
	  /* Rules 037-038. */
	  if (*wcs) vptr = &((*wcs)->equinox);
	  type = FLOAT;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^EPOCH{ALT}"  " {
	  /* Rule 039. */
	  sscanf(yytext, "EPOCH%c", &a);
	
	  if (a == ' ' || relax & (WCSHDR_all | WCSHDR_EPOCHa)) {
	    if (*wcs) {
	      vptr = epoch;
	      if (a >= 'A') {
	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
	      }
	    }
	
	    unput(' ');
	    type = FLOAT;
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    sprintf(errmsg, "EPOCH keyword may not have an alternate "
	                    "version code");
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^RESTFREQ {
	  /* Rule 040. */
	  unput(' ');
	  if (*wcs) vptr = &((*wcs)->restfrq);
	  type = FLOAT;
	  BEGIN(CCCCCCCa);
	}

^RESTFRQ |
^RFRQ	{
	  /* Rules 041-042. */
	  if (*wcs) vptr = &((*wcs)->restfrq);
	  type = FLOAT;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^RESTWAV |
^RWAV	{
	  /* Rules 043-044. */
	  if (*wcs) vptr = &((*wcs)->restwav);
	  type = FLOAT;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^SPECSYS |
^SPEC	{
	  /* Rules 045-046. */
	  if (*wcs) vptr = (*wcs)->specsys;
	  type = STRING;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^SSYSOBS |
^SOBS	{
	  /* Rules 047-048. */
	  if (*wcs) vptr = (*wcs)->ssysobs;
	  type = STRING;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^VELREF{ALT}" " {
	  /* Rule 049. */
	  sscanf(yytext, "VELREF%c", &a);
	
	  if (a == ' ' || relax & (WCSHDR_all | WCSHDR_VELREFa)) {
	    if (*wcs) {
	      vptr = velref;
	      if (a >= 'A') {
	        vptr = (void *)((int *)vptr + alts[a-'A'+1]);
	      }
	    }
	
	    unput(' ');
	    type = INTEGER;
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    sprintf(errmsg, "VELREF keyword may not have an alternate "
	                    "version code");
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^VELOSYS |
^VSYS	{
	  /* Rules 050-051. */
	  if (*wcs) vptr = &((*wcs)->velosys);
	  type = FLOAT;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^SSYSSRC |
^SSRC	{
	  /* Rules 052-053. */
	  if (*wcs) vptr = (*wcs)->ssyssrc;
	  type = STRING;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^VSOURCE{ALT} {
	  /* Rule 054. */
	  sscanf(yytext, "VSOURCE%c", &a);
	
	  if (relax & (WCSHDR_all | WCSHDR_VSOURCEa)) {
	    if (*wcs) {
	      vptr = vsource;
	      if (a >= 'A') {
	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
	      }
	    }
	
	    unput(' ');
	    type = FLOAT;
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    sprintf(errmsg, "Deprecated VSOURCEa keyword rejected");
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^ZSOURCE |
^ZSOU	{
	  /* Rules 055-056. */
	  if (*wcs) vptr = &((*wcs)->zsource);
	  type = FLOAT;
	  if (yyleng == 7) {
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^OBSGEO-X |
^OBSGX	{
	  /* Rules 057-058. */
	  if (*wcs) vptr = (*wcs)->obsgeo;
	  type = FLOAT;
	  if (yyleng == 8) {
	    BEGIN(CCCCCCCC);
	  } else {
	    BEGIN(CCCCCn);
	  }
	}

^OBSGEO-Y |
^OBSGY	{
	  /* Rules 059-060. */
	  if (*wcs) vptr = (*wcs)->obsgeo + 1;
	  type = FLOAT;
	  if (yyleng == 8) {
	    BEGIN(CCCCCCCC);
	  } else {
	    BEGIN(CCCCCn);
	  }
	}

^OBSGEO-Z |
^OBSGZ	{
	  /* Rules 061-062. */
	  if (*wcs) vptr = (*wcs)->obsgeo + 2;
	  type = FLOAT;
	  if (yyleng == 8) {
	    BEGIN(CCCCCCCC);
	  } else {
	    BEGIN(CCCCCn);
	  }
	}

^DATE-OBS |
^DOBS	{
	  /* Rules 063-064. */
	  if (*wcs) vptr = (*wcs)->dateobs;
	  type = STRING;
	  if (yyleng == 8) {
	    BEGIN(CCCCCCCC);
	  } else {
	    BEGIN(CCCCCn);
	  }
	}

^DATE-AVG |
^DAVG {
	  /* Rules 065-066. */
	  if (*wcs) vptr = (*wcs)->dateavg;
	  type = STRING;
	  if (yyleng == 8) {
	    BEGIN(CCCCCCCC);
	  } else {
	    BEGIN(CCCCCn);
	  }
	}

^MJD-OBS" " |
^MJDOB	{
	  /* Rules 067-068. */
	  if (*wcs) vptr = &((*wcs)->mjdobs);
	  type = FLOAT;
	  if (yyleng == 8) {
	    BEGIN(CCCCCCCC);
	  } else {
	    BEGIN(CCCCCn);
	  }
	}

^MJD-AVG" " |
^MJDA {
	  /* Rules 069-070 */
	  if (*wcs) vptr = &((*wcs)->mjdavg);
	  type = FLOAT;
	  if (yyleng == 8) {
	    BEGIN(CCCCCCCC);
	  } else {
	    BEGIN(CCCCCn);
	  }
	}

^END" "{77} {
	  /* Rule 071. */
	  yyless(0);
	  if (wcsbth_ncards) {
	    sprintf(errmsg, "Illegal cards following END card");
	    BEGIN(ERROR);
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^.	{
	  /* Rule 072. */
	  yyless(0);
	  BEGIN(DISCARD);
	}

<TCROTn>{I1}{ALT}" " |
<TCROTn>{I2}{ALT} {
	  /* Rules 073-074. */
	  sscanf(yytext, "%d%c", &n, &a);
	  if (a == ' ' || relax & (WCSHDR_all | WCSHDR_CROTAia)) {
	    if (pass == 2) {
	      i = wcsbth_colax(wcs, alts, n, a);
	      idx = 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);
	  }
	}

<TCROTn>{I3} {
	  /* Rule 075. */
	  sscanf(yytext, "%d", &n);
	  a = ' ';
	  if (pass == 2) {
	    i = wcsbth_colax(wcs, alts, n, a);
	    idx = i - 1;
	  }
	  BEGIN(VALUE);
	}

<TCROTn>. {
	  /* Rule 076. */
	  BEGIN(DISCARD);
	}

<PROJPm>{I0}"  " {
	  /* Rule 077. */
	  if (relax & (WCSHDR_all | WCSHDR_PROJPn)) {
	    sscanf(yytext, "%d", &m);
	    i = 0;
	    a = ' ';
	    idx = -1;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    sprintf(errmsg, "Defunct PROJPn keyword rejected");
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

<PROJPm>. {
	  /* Rule 078. */
	  BEGIN(DISCARD);
	}

<CCCCCn>{I1}{ALT}" " |
<CCCCCn>{I2}{ALT} {
	  /* Rules 079-080. */
	  sscanf(yytext, "%d%c", &n, &a);

	  if (a == ' ' || (relax & (WCSHDR_all | WCSHDR_LONGKEY))) {
	    if (pass == 2) {
	      i = wcsbth_colax(wcs, alts, n, a);
	      idx = i - 1;
	    }
	    BEGIN(VALUE);

	  } else if (relax & WCSHDR_reject) {
	    sprintf(errmsg, "Non-standard alternate keyword rejected");
	    BEGIN(ERROR);

	  } else {
	    BEGIN(DISCARD);
	  }
	}

<CCCCCn>{I3} {
	  /* Rules 81. */
	  sscanf(yytext, "%d", &n);
	  a = ' ';
	  if (pass == 2) {
	    i = wcsbth_colax(wcs, alts, n, a);
	    idx = i - 1;
	  }
	  BEGIN(VALUE);
	}

<CCCCna>{I1}{ALT}" " |
<CCCCna>{I2}{ALT} {
	  /* Rules 082-083. */
	  sscanf(yytext, "%d%c", &n, &a);
	  if (pass == 2) {
	    i = wcsbth_colax(wcs, alts, n, a);
	    idx = i - 1;
	  }
	  BEGIN(VALUE);
	}

<CCCCna>{I3} {
	  /* Rule 084. */
	  sscanf(yytext, "%3d", &n);
	  a = ' ';
	  if (pass == 2) {
	    i = wcsbth_colax(wcs, alts, n, a);
	    idx = i - 1;
	  }
	  BEGIN(VALUE);
	}

<CCCCna>. {
	  /* Rule 085. */
	  BEGIN(DISCARD);
	}

<CCCn_ka>{I1}_{I1}{ALT}" " |
<CCCn_ka>{I1}_{I2}{ALT} |
<CCCn_ka>{I2}_{I1}{ALT} |
<CCn_ka>{I1}_{I1}{ALT}"  " |
<CCn_ka>{I1}_{I2}{ALT}" " |
<CCn_ka>{I2}_{I1}{ALT}" " |
<CCn_ka>{I1}_{I3}{ALT} |
<CCn_ka>{I2}_{I2}{ALT} |
<CCn_ka>{I3}_{I1}{ALT} {
	  /* Rules 086-094. */
	  sscanf(yytext, "%d_%d%c", &n, &k, &a);
	  if (pass == 2) {
	    wcsp = *wcs;
	    if (a != ' ') {
	      wcsp += alts[a-'A'+1];
	    }
	
	    i = wcsbth_colax(wcs, alts, n, a);
	    j = wcsbth_colax(wcs, alts, k, a);
	    idx = (i-1)*(wcsp->naxis) + j - 1;
	  }
	  BEGIN(VALUE);
	}

<CCCn_ka>{I1}_{I3} |
<CCCn_ka>{I2}_{I2} |
<CCCn_ka>{I3}_{I1} |
<CCn_ka>{I1}_{I4} |
<CCn_ka>{I2}_{I3} |
<CCn_ka>{I3}_{I2} |
<CCn_ka>{I4}_{I1} {
	  /* Rules 095-101. */
	  sscanf(yytext, "%d_%d", &n, &k);
	  a = ' ';
	  if (pass == 2) {
	    i = wcsbth_colax(wcs, alts, n, a);
	    j = wcsbth_colax(wcs, alts, k, a);
	    idx = (i-1)*((*wcs)->naxis) + j - 1;
	  }
	  BEGIN(VALUE);
	}

<CCCn_ka>. |
<CCn_ka>. {
	  /* Rule 102-103. */
	  BEGIN(DISCARD);
	}

<CCCn_ma>{I1}_{I0}{ALT}" " |
<CCCn_ma>{I1}_{I2}{ALT} |
<CCCn_ma>{I2}_{I0}{ALT} |
<CCn_ma>{I1}_{I0}{ALT}"  " |
<CCn_ma>{I1}_{I2}{ALT}" " |
<CCn_ma>{I2}_{I0}{ALT}" " |
<CCn_ma>{I1}_{I3}{ALT} |
<CCn_ma>{I2}_{I2}{ALT} |
<CCn_ma>{I3}_{I0}{ALT} {
	  /* Rules 104-112. */
	  sscanf(yytext, "%d_%d%c", &n, &m, &a);
	  if (pass == 2) {
	    i = wcsbth_colax(wcs, alts, n, a);
	    idx = i - 1;
	  }
	  BEGIN(VALUE);
	}

<CCCn_ma>{I1}_{I3} |
<CCCn_ma>{I1}_{I2} |
<CCCn_ma>{I1}_{I0} |
<CCn_ma>{I1}_{I4} |
<CCn_ma>{I2}_{I3} |
<CCn_ma>{I3}_{I2} |
<CCn_ma>{I4}_{I0} {
	  /* Rules 113-119. */
	  sscanf(yytext, "%d_%d", &n, &m);
	  a = ' ';
	  if (pass == 2) {
	    i = wcsbth_colax(wcs, alts, n, a);
	    idx = i - 1;
	  }
	  BEGIN(VALUE);
	}

<CCCn_ma>. |
<CCn_ma>. {
	  /* Rules 120-121. */
	  BEGIN(DISCARD);
	}

<CCCCCCCa>{ALT} {
	  /* Rule 122. */
	  idx = -1;
	  sscanf(yytext, "%c", &a);
	  BEGIN(VALUE);
	}

<CCCCCCCa>. {
	  /* Rule 123. */
	  BEGIN(DISCARD);
	}

<CCCCCCCC>. {
	  /* Rule 124. */
	  unput(yytext[0]);
	  idx = -1;
	  a = 0;
	  BEGIN(VALUE);
	}

<VALUE>=" "+ {
	  /* Rule 125. */
	  if (type == INTEGER) {
	    BEGIN(INTEGER_VAL);
	  } else if (type == FLOAT) {
	    BEGIN(FLOAT_VAL);
	  } else if (type == STRING) {
	    BEGIN(STRING_VAL);
	  } else {
	    sprintf(errmsg, "Internal parser ERROR, bad data type: %d", type);
	    BEGIN(ERROR);
	  }
	}

<VALUE>. {
	  /* Rule 126. */
	  sprintf(errmsg, "Invalid KEYWORD = VALUE syntax");
	  BEGIN(ERROR);
	}

<INTEGER_VAL>{INTEGER} {
	  /* Rule 127. */
	  if (pass == 1) {
	    wcsbth_naxes(n, k, a, alts, colalt, npptr);
	    BEGIN(FLUSH);
	
	  } else {
	    if (vptr) {
	      /* Determine the coordinate representation. */
	      for (iax = 0; iax < *nwcs; iax++) {
	        /* The loop here is for keywords that apply */
		/* to every alternate; these have a == 0. */
	        if (a >= 'A') {
	          iax = alts[a-'A'+1];
	        }
	
	        wptr = vptr;
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
	          wptr = (void *)((char *)vptr + voff);
	        }
	
	        /* Apply keyword parameterization. */
	        if (idx >= 0) {
	          wptr = *((int **)wptr) + idx;
	        }
	
	        /* Read the keyvalue. */
	        sscanf(yytext, "%d", (int *)wptr);
	
	        if (a) break;
	      }
	
	      BEGIN(COMMENT);
	
	    } else {
	      sprintf(errmsg, "Internal parser ERROR, null int pointer");
	      BEGIN(ERROR);
	    }
	  }
	}

<INTEGER_VAL>. {
	  /* Rule 128. */
	  sprintf(errmsg, "An integer value was expected");
	  BEGIN(ERROR);
	}

<FLOAT_VAL>{FLOAT} {
	  /* Rule 129. */
	  if (pass == 1) {
	    wcsbth_naxes(n, k, a, alts, colalt, npptr);
	    BEGIN(FLUSH);
	
	  } else {
	    if (vptr) {
	      /* Determine the coordinate representation. */
	      for (iax = 0; iax < *nwcs; iax++) {
	        /* The loop here is for keywords like MJD-OBS that */
		/* apply to every alternate; these have a == 0.  */
	        if (a >= 'A') {
	          iax = alts[a-'A'+1];
	        }
	
	        wptr = vptr;
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
	          wptr = (void *)((char *)vptr + voff);
	        }
	
	        /* Apply keyword parameterization. */
	        if (idx >= 0) {
	          wptr = *((double **)wptr) + idx;
	
	        } else if (npptr == npv) {
	          ipx = (*wcs+iax)->npv++;
	          (*wcs+iax)->pv[ipx].i = i;
	          (*wcs+iax)->pv[ipx].m = m;
	          wptr = &((*wcs+iax)->pv[ipx].value);
	        }
	
	        /* Read the keyvalue. */
	        sscanf(yytext, "%lf", (double *)wptr);
	
	        /* Flag the presence of TPn_ka, or TCn_ka and/or TCROTna. */
	        if (altlin) {
	          (*wcs+iax)->altlin |= altlin;
	          altlin = 0;
	        }
	
	        if (a) break;
	      }
	
	      BEGIN(COMMENT);
	
	    } else {
	      sprintf(errmsg, "Internal parser ERROR, null float pointer");
	      BEGIN(ERROR);
	    }
	  }
	}

<FLOAT_VAL>. {
	  /* Rule 130. */
	  sprintf(errmsg, "A floating-point value was expected");
	  BEGIN(ERROR);
	}

<STRING_VAL>{STRING} {
	  /* Rule 131. */
	  if (pass == 1) {
	    wcsbth_naxes(n, k, a, alts, colalt, npptr);
	    BEGIN(FLUSH);
	
	  } else {
	    if (vptr) {
	      /* Determine the coordinate representation. */
	      for (iax = 0; iax < *nwcs; iax++) {
	        /* The loop here is for keywords like DATE-OBS that */
		/* apply to every alternate; these have a == 0.   */
	        if (a >= 'A') {
	          iax = alts[a-'A'+1];
	        }
	
	        wptr = vptr;
	        if (iax) {
	          voff = (char *)(*wcs+iax) - (char *)(*wcs);
	          wptr = (void *)((char *)vptr + voff);
	        }
	
	        /* Apply keyword parameterization. */
	        if (idx >= 0) {
	          wptr = *((char (**)[72])wptr) + idx;
	
	        } else if (npptr == nps) {
	          ipx = (*wcs+iax)->nps++;
	          (*wcs+iax)->ps[ipx].i = i;
	          (*wcs+iax)->ps[ipx].m = m;
	          wptr = (*wcs+iax)->ps[ipx].value;
	        }
	
	        /* 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];
	          }
	
	          if (cptr[jx] == '\0') {
	            if (ix) cptr[ix-1] = '\0';
	            break;
	          } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
	            jx++;
	          }
	
	          ix++;
	        }
	
	        if (a) break;
	      }
	
	      BEGIN(COMMENT);
	
	    } else {
	      sprintf(errmsg, "Internal parser ERROR, null string pointer");
	      BEGIN(ERROR);
	    }
	  }
	}

<STRING_VAL>. {
	  /* Rule 132. */
	  sprintf(errmsg, "A string value was expected");
	  BEGIN(ERROR);
	}

<COMMENT>" "*\/.* |
<COMMENT>" "* {
	  /* Rules 133-134. */
	  BEGIN(FLUSH);
	}

<COMMENT>. {
	  /* Rule 135. */
	  sprintf(errmsg, "Malformed inline comment");
	  BEGIN(ERROR);
	}

<DISCARD>.* {
	  /* Rule 136. */
	  if (pass == 2) {
	    if (ctrl < 0) {
	      /* Preserve discards. */
	      if (hptr < wcsbth_hdr-80) {
	        strncpy(hptr, wcsbth_hdr-80, 80);
	      }
	      hptr += 80;
	
	    } else if (ctrl > 2) {
	      fprintf(stderr, "%.80s\n  Discarded.\n", wcsbth_hdr-80);
	    }
	  }
	  BEGIN(FLUSH);
	}

<ERROR>.* {
	  /* Rule 137. */
	  (*nreject)++;
	  if (pass == 2) {
	    if (ctrl == -1) {
	      if (hptr < wcsbth_hdr-80) {
	        /* Preserve rejects. */
	        strncpy(hptr, wcsbth_hdr-80, 80);
	      }
	      hptr += 80;
	    }
	
	    if (abs(ctrl) > 1) {
	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcsbth_hdr-80, *nreject,
	        errmsg);
	    }
	  }
	  BEGIN(FLUSH);
	}

<FLUSH>.*\n {
	  /* Rule 138. */
	  i = j = k = m = n = 0;
	  a = ' ';
	  type = -1;
	  altlin = 0;
	  npptr = 0x0;
	  BEGIN(INITIAL);
	}

<<EOF>> {
	  /* Rule unnumbered: End-of-input. */
	  if (pass == 1) {
	    if ((status = wcsbth_inits(colalt, npv, nps, nwcs, wcs, alts)) ||
	         *nwcs == 0) {
	      yy_delete_buffer(YY_CURRENT_BUFFER);
	      return status;
	    }
	
	    if (abs(ctrl) > 2) {
	      if (*nwcs == 1) {
	        fprintf(stderr, "Found one coordinate representation.\n");
	      } else {
	        fprintf(stderr, "Found %d coordinate representations.\n",
	          *nwcs);
	      }
	    }
	
	    wcsbth_hdr = header;
	    wcsbth_ncards = ncards;
	    *nreject = 0;
	
	    pass = 2;
	    i = j = k = m = n = 0;
	    a = ' ';
	    type = -1;
	
	    yyrestart(yyin);
	
	  } else {
	    if (ctrl < 0) {
	      *hptr = '\0';
	    } else if (ctrl == 1) {
	      fprintf(stderr, "%d WCS cards were rejected.\n", *nreject);
	    }
	
	    status = wcsbth_final(alts, epoch, velref, vsource, nwcs, wcs);
	    yy_delete_buffer(YY_CURRENT_BUFFER);
	    return 0;
	  }
	}

%%

/*----------------------------------------------------------------------------
*   Determine the number of coordinate representations (up to 27) and the
*   table columns associated with in each, and count the number of TVn_ma and
*   TSn_ma cards in each representation.
*---------------------------------------------------------------------------*/

void wcsbth_naxes(int n, int k, char a, int alts[], int colalt[], int *npptr)

{
  /* During the first pass alts[] is used to determine the number of        */
  /* coordinate representations (up to 27).                                 */
  /*                                                                        */
  /* colalt[] is used as a 2-D bit array of dimension (1+NCOL) * 27 which   */
  /* records the table columns that are associated with WCS keywords with   */
  /* an "a" descriptor.  At the end of the first pass this is used by       */
  /* wcsbth_inits() to determine the number of coordinate axes in each      */
  /* representation and the corresponding table column numbers.             */

  int iax, ncols;

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

  alts[iax] = 1;

  ncols = colalt[0];

  if (0 < n && n <= ncols) {
    colalt[n] |= (1 << iax);
  }

  if (0 < k && k <= ncols) {
    colalt[k] |= (1 << iax);
  }

  if (npptr) {
    npptr[iax]++;
  }
}


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

int wcsbth_inits(
  int colalt[],
  int npv[],
  int nps[],
  int *nwcs,
  struct wcsprm **wcs,
  int alts[])

{
  int iax, icol, ix, mask, ncols, npsmax, npvmax, status = 0;
  struct wcsprm *wcsp;

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

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

    /* Record the current values of NPVMAX and NPSMAX. */
    npvmax = wcsnpv(-1);
    npsmax = wcsnps(-1);

    /* Determine the number of axes in each coordinate representation. */
    ncols = colalt[0];
    for (iax = 0, mask = 1; iax < 27; iax++, mask <<= 1) {
      if (alts[iax]) {
        alts[iax] = 0;
        for (icol = 1; icol <= ncols; icol++) {
          if (colalt[icol] & mask) {
            alts[iax]++;
          }
        }
      }
    }

    /* Initialize each wcsprm struct. */
    wcsp = *wcs;
    *nwcs = 0;
    for (iax = 0; iax < 27; iax++) {
      if (alts[iax]) {
        wcsp->flag = -1;
        wcsnpv(npv[iax]);
        wcsnps(nps[iax]);
        if ((status = wcsini(1, alts[iax], wcsp))) {
          wcsvfree(nwcs, wcs);
          break;
        }

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

        /* Record the table column numbers. */
        mask = (1 << iax);
        for (icol = 1, ix = 0; icol <= ncols; icol++) {
          if (colalt[icol] & mask) {
            wcsp->colax[ix++] = icol;
          }
        }

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

        wcsp++;
      }
    }

    /* Restore the original values of NPVMAX and NPSMAX. */
    wcsnpv(npvmax);
    wcsnps(npsmax);
  }

  return status;
}


/*----------------------------------------------------------------------------
*   Return the axis number associated with the specified column number in a
*   particular coordinate representation.
*---------------------------------------------------------------------------*/

int wcsbth_colax(struct wcsprm **wcs, int alts[], int n, char a)

{
  int ix;
  struct wcsprm *wcsp;

  wcsp = *wcs;
  if (a != ' ') {
    wcsp += alts[a-'A'+1];
  }

  for (ix = 0; ix < wcsp->naxis; ix++) {
    if (wcsp->colax[ix] == n) {
      return ++ix;
    }
  }

  return 0;
}


/*----------------------------------------------------------------------------
*   Interpret any VELREF cards encountered for each coordinate representation.
*---------------------------------------------------------------------------*/

int wcsbth_final(
  int alts[],
  double epoch[],
  int velref[],
  double vsource[],
  int *nwcs,
  struct wcsprm **wcs)

{
  static char *specsys[] = {"LSRK", "BARYCENT", "TOPOCENT",
                            "LSRD", "GEOCENTR", "SOURCE", "GALACTOC"};
  int iax, ivf, status;
  double beta, c = 299792458.0;

  for (iax = 0; iax < *nwcs; iax++) {
    /* Check for EPOCH overriding EQUINOXa. */
    if (undefined((*wcs+iax)->equinox) && !undefined(epoch[iax])) {
      /* Set EQUINOXa. */
      (*wcs+iax)->equinox = epoch[iax];
    }

    /* 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]);
        }
      }
    }

    /* Check for VSOURCEa overriding ZSOURCEa. */
    if (undefined((*wcs+iax)->zsource) && !undefined(vsource[iax])) {
      /* Convert relativistic Doppler velocity to redshift. */
      beta = vsource[iax]/c;
      (*wcs+iax)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
    }

    /* Interpret -TAB header cards. */
    if ((status = wcstab(*wcs+iax))) {
       wcsvfree(nwcs, wcs);
       return status;
    }
  }

  return 0;
}
@


0.0.1.2
log
@Revised use of the WCSHDR_all macro.
@
text
@d29 1
a29 1
*   $Id: wcsbth.l,v 0.0.1.1 2007/07/11 02:05:52 cal103 Exp cal103 $
d227 1
a227 1
	    if (relax & WCSHDR_LONGKEY) {
d250 1
a250 1
	    if (relax & WCSHDR_LONGKEY) {
d365 1
a365 1
	    if (relax & WCSHDR_LONGKEY) {
d393 1
a393 1
	    if (relax & WCSHDR_LONGKEY) {
d466 1
a466 1
	  if (a == ' ' || relax & WCSHDR_EPOCHa) {
d548 1
a548 1
	  if (a == ' ' || relax & WCSHDR_VELREFa) {
d598 1
a598 1
	  if (relax & WCSHDR_VSOURCEa) {
d736 1
a736 1
	  if (a == ' ' || relax & WCSHDR_CROTAia) {
d771 1
a771 1
	  if (relax & WCSHDR_PROJPn) {
d797 1
a797 1
	  if (a == ' ' || (relax & WCSHDR_LONGKEY)) {
@


0.0.1.3
log
@Replaced use of the obsolete term "card".
@
text
@d29 1
a29 1
*   $Id: wcsbth.l,v 0.0.1.2 2007/08/02 04:34:40 cal103 Exp cal103 $
d33 1
a33 1
*   definition for parsing the WCS keyrecords for a pixel list from a FITS
d47 1
a47 1
*   TVk_ma and TSk_ma keywords in each representation.
d54 1
a54 1
*   The parser does not check for duplicated keywords, it accepts the last
d99 1
a99 1
#define YY_DECL int wcsbth(char *header, int nkeyrec, int relax, int ctrl, \
d104 1
a104 1
	  if (wcsbth_nkeyrec) { \
d108 1
a108 1
	    wcsbth_nkeyrec--; \
d122 1
a122 1
int  wcsbth_nkeyrec;
d155 1
a155 1
	wcsbth_nkeyrec = nkeyrec;
d718 2
a719 2
	  if (wcsbth_nkeyrec) {
	    sprintf(errmsg, "Illegal keyrecords following END keyrecord");
d1238 1
a1238 1
	    wcsbth_nkeyrec = nkeyrec;
d1252 1
a1252 1
	      fprintf(stderr, "%d WCS keyrecords were rejected.\n", *nreject);
d1266 1
a1266 1
*   TSn_ma keywords in each representation.
d1423 1
a1423 2
*   Interpret any VELREF keywords encountered for each coordinate
*   representation.
d1465 1
a1465 1
    /* Interpret -TAB header keywords. */
@


0.0.1.4
log
@Checkpoint: handling of BINTABLE image array keywords.
@
text
@a1 31

    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: wcsbth.l,v 0.0.1.3 2007/08/02 04:49:30 cal103 Exp cal103 $
*=============================================================================
d3 2
a4 4
*   wcsbth.l is a Flex description file containing the definition of a lexical
*   scanner for parsing the WCS keyrecords for one or more image arrays and/or
*   pixel lists in a FITS binary table header.  It can also handle primary
*   image and image extension headers.
d6 4
a9 2
*   wcsbth.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a
*   description of the user interface and operating notes.
d11 4
a14 8
*   Implementation notes
*   --------------------
*   wcsbth() may be invoked with an option that causes it to recognise the
*   image-header form of WCS keywords as defaults for each alternate
*   coordinate representation (up to 27).  By design, with this option enabled
*   wcsbth() can also handle primary image and image extension headers,
*   effectively treating them as a single-column binary table though with WCS
*   keywords of a different form.
d16 3
a18 9
*   NAXIS is always 2 for binary tables, it refers to the two-dimensional
*   nature of the table.  Thus NAXIS does not count the number of image axes
*   in either image arrays or pixels lists and for the latter there is not
*   even a formal equivalent of WCSAXESa.  Hence NAXIS is always ignored and a
*   first pass through the header is required to determine the number of
*   images, the number of alternate coordinate representations for each image
*   (up to 27), and the number of coordinate axes in each representation; this
*   pass also counts the number of iPVn_ma and iPSn_ma or TVk_ma and TSk_ma
*   keywords in each representation.
d20 7
a26 5
*   On completion of the first pass, the association between column number
*   and axis number is defined for each representation of a pixel list.
*   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.
d28 3
a30 2
*   It is permissible for a scalar table column to contain degenerate (single-
*   point) image arrays and simultaneously form one axis of a pixel list.
d32 3
a34 2
*   The parser does not check for duplicated keywords, it accepts the first
*   encountered.
d36 1
a36 1
*   wcsbth() does not currently handle the Greenbank convention.
d38 2
a39 1
*>>>
d41 7
a47 3
*  * DATE-AVG DATE-OBS MJD-AVG MJD-OBS OBSGEO-X/Y/Z and their bintable
*    equivalents, DAVGn DOBSn MJDAn MJDOBn OBSGXn OBSGYn OBSGZn, do not cause
*    a wcsprm struct to be created.
d49 4
a52 2
*  * Cross-references:
*    WCSXna -> WCSTna, e.g. WCSX13A -> WCST12B (fully specified)
d54 2
a55 4
*  ::: Add function argument to restrict the columns considered.
*  ::: Add function argument to restrict the keytype considered.
*  ::: Add function argument to return the number of keytypes found.
*  ::: Splitting of pixel lists.
d80 2
a81 8
%x CCCCCia   iCCCna iCCCCn    TCCCna TCCCCn
%x CCi_ja    ijCCna           TCn_ka TCCn_ka
%x CROTAi           iCROTn           TCROTn
%x CCi_ma    iCn_ma iCCn_ma   TCn_ma TCCn_ma
%x PROJPm
%x CCCCCCCC CCCCCCCa
%x CCCCna   CCCCCna
%x CCCCn    CCCCCn
a94 1
			/* Codes used for keyvalue data types. */
a98 13
			/* Bit masks used for keyword types:        */
#define IMGAUX  0x1	/* Auxiliary image header, e.g. LONPOLEa or */
			/* DATE-OBS.                                */
#define IMGAXIS 0x2	/* Image header with axis number, e.g.      */
                        /* CTYPEia.                                 */
#define IMGHEAD 0x3	/* Image header of either type.             */
#define BIMGARR 0x4	/* Binary table image array with axis       */
			/* number, e.g. iCTYna.                     */
#define PIXLIST 0x8	/* Pixel list, e.g. TCTYna.                 */
#define BINTAB  0xC	/* Shared binary table image array (without */
			/* axis number) or pixel list, e.g. LONPna  */
			/* or OBSGXn.                               */

d115 4
a118 6
/* A convenience macro to get around incompatibilities between unput() and
   yyless(): put yytext followed by a blank back onto the input stream. */
#define WCSBTH_PUTBACK \
  sprintf(stmp, "%s ", yytext); \
  itmp = strlen(stmp); \
  while (itmp) unput(stmp[--itmp]);
d124 6
a129 28
/* Struct used internally for header bookkeeping. */
struct wcsbth_alts {
  int ncol;
  short int (*arridx)[27];
  short int pixidx[27];
  unsigned int  *pixlist;

  unsigned char (*npv)[27];
  unsigned char (*nps)[27];
  unsigned char pixnpv[27];
  unsigned char pixnps[27];

  int iax, icol, imgherit;
};

int wcsbth_pass1(int keytype, int i, int j, int n, int k, char a, char ptype,
                 struct wcsbth_alts *alts);
int wcsbth_init1(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);

struct wcsprm *wcsbth_idx(struct wcsprm *wcs, struct wcsbth_alts *alts,
                 int keytype, int n, char a);
int wcsbth_colax(struct wcsprm *wcs, struct wcsbth_alts *alts, int k, char a);

int wcsbth_epoch(void *wptr);
int wcsbth_velref(void *wptr);
int wcsbth_vsource(void *wptr);

int wcsbth_final(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
d134 1
a134 1
	/* Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka. */
d138 15
a152 7
	char *cptr, *errmsg, errtxt[80], *extkey, *hptr, ptype, stmp[16];
	int  altlin, iax, icol, ipass, ipx, itmp, ix, jx, keytype, npass,
	     status, valtype, voff;
	void   *vptr, *wptr;
	struct wcsbth_alts alts;
	struct wcsprm *wcsp, wcstem;
	int (*special)(void *);
a153 1
	/* Parameters used to implement YY_INPUT. */
a156 1
	/* Our handle on the input stream. */
d159 2
d162 2
a163 4
	/* Keyword parameters. */
	i = j = 0;
	n = k = 0;
	m = 0;
d165 2
a166 20
	
	/* Header bookkeeping. */
	alts.ncol = 0;
	alts.arridx  = 0x0;
	alts.pixlist = 0x0;
	alts.npv = 0x0;
	alts.nps = 0x0;
	
	for (iax = 0; iax < 27; iax++) {
	  alts.pixidx[iax] = 0;
	  alts.pixnpv[iax] = 0;
	  alts.pixnps[iax] = 0;
	}

	/* For decoding the keyvalue. */
	keytype =  0;
	valtype = -1;
	vptr    = 0x0;
	
	/* For keywords that require special handling. */
d168 4
a171 2
	ptype  = ' ';
	special = 0x0;
a172 6
	/* The data structures produced. */
	*nwcs = 0;
	*wcs  = 0x0;
	
	ipass = 1;
	npass = 2;
d177 3
a179 4
	  if (ipass == 1) {
	    if (alts.ncol == 0) {
	      sscanf(yytext, "TFIELDS = %d", &(alts.ncol));
	      BEGIN(FLUSH);
d181 4
a184 3
	    } else {
	      errmsg = "Duplicate or out-of-sequence TFIELDS keyword";
	      BEGIN(ERROR);
d187 2
a188 2
	  } else {
	    BEGIN(FLUSH);
d190 1
d193 9
a201 5
^WCSAXES{ALT}=" "" "*{INTEGER} {
	  if (ipass == 1) {
	    /* ::: WCSHDR_ALLIMG? */
	    sscanf(yytext, "WCSAXES%c= %d", &a, &i);
	    wcsbth_pass1(IMGAXIS, i, 0, 0, 0, a, ' ', &alts);
a202 1
	  BEGIN(FLUSH);
d205 9
a213 8
^WCAX{I1}{ALT}"  = "" "*{INTEGER} |
^WCAX{I2}{ALT}" = "" "*{INTEGER}  |
^WCAX{I3}{ALT}"= "" "*{INTEGER} {
	  if (ipass == 1) {
	    /* Note that a blank in the sscanf() format string matches zero
	       or more of them in the input. */
	    sscanf(yytext, "WCAX%d%c = %d", &n, &a, &i);
	    wcsbth_pass1(BIMGARR, i, 0, n, 0, a, ' ', &alts);
a214 1
	  BEGIN(FLUSH);
d217 21
a237 5
^WCST{I1}{ALT}"  = "" "*{STRING} |
^WCST{I2}{ALT}" = "" "*{STRING} |
^WCST{I3}{ALT}"= "" "*{STRING} {
	  /* ::: Cross-reference supplier. */
	  BEGIN(FLUSH);
d240 8
a247 10
^WCSX{I1}{ALT}"  = "" "*{STRING} |
^WCSX{I2}{ALT}" = "" "*{STRING} |
^WCSX{I3}{ALT}"= "" "*{STRING} {
	  /* ::: Cross-reference consumer. */
	  BEGIN(FLUSH);
	}

^CRPIX	{
	  valtype = FLOAT;
	  vptr = &(wcstem.crpix);
d249 9
a257 13
	  extkey = "CRPIXja";
	  BEGIN(CCCCCia);
	}

^{I1}CRP  |
^{I1}CRPX {
	  valtype = FLOAT;
	  vptr = &(wcstem.crpix);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    BEGIN(iCCCna);
d259 1
a259 2
	    extkey = "jCRPXn";
	    BEGIN(iCCCCn);
d263 7
a269 7
^TCRP	|
^TCRPX	{
	  valtype = FLOAT;
	  vptr = &(wcstem.crpix);
	
	  if (yyleng == 4) {
	    BEGIN(TCCCna);
d271 1
a271 2
	    extkey = "TCRPXn";
	    BEGIN(TCCCCn);
a274 8
^PC	{
	  valtype = FLOAT;
	  vptr = &(wcstem.pc);
	  altlin = 1;
	
	  extkey = "PCi_ja";
	  BEGIN(CCi_ja);
	}
d276 8
a283 8
^{I2}PC	{
	  valtype = FLOAT;
	  vptr = &(wcstem.pc);
	  altlin = 1;
	
	  sscanf(yytext, "%1d%1d", &i, &j);
	
	  BEGIN(ijCCna);
d286 7
a292 8
^TP	|
^TPC	{
	  valtype = FLOAT;
	  vptr = &(wcstem.pc);
	  altlin = 1;
	
	  if (yyleng == 2) {
	    BEGIN(TCn_ka);
d294 1
a294 2
	    extkey = "TPCn_ka";
	    BEGIN(TCCn_ka);
d298 10
a307 7
^CD	{
	  valtype = FLOAT;
	  vptr = &(wcstem.cd);
	  altlin = 1;
	
	  extkey = "CDi_ja";
	  BEGIN(CCi_ja);
d310 10
a319 8
^{I2}CD	{
	  valtype = FLOAT;
	  vptr = &(wcstem.cd);
	  altlin = 1;
	
	  sscanf(yytext, "%1d%1d", &i, &j);
	
	  BEGIN(ijCCna);
d322 7
a328 8
^TC	|
^TCD	{
	  valtype = FLOAT;
	  vptr = &(wcstem.cd);
	  altlin = 1;
	
	  if (yyleng == 2) {
	    BEGIN(TCn_ka);
d330 1
a330 2
	    extkey = "TCDn_ka";
	    BEGIN(TCCn_ka);
d334 10
a343 6
^CDELT	{
	  valtype = FLOAT;
	  vptr = &(wcstem.cdelt);
	
	  extkey = "CDELTia";
	  BEGIN(CCCCCia);
d346 7
a352 9
^{I1}CDE  |
^{I1}CDLT {
	  valtype = FLOAT;
	  vptr = &(wcstem.cdelt);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    BEGIN(iCCCna);
d354 1
a354 2
	    extkey = "iCDLTn";
	    BEGIN(iCCCCn);
d358 15
a372 7
^TCDE	|
^TCDLT	{
	  valtype = FLOAT;
	  vptr = &(wcstem.cdelt);
	
	  if (yyleng == 4) {
	    BEGIN(TCCCna);
d374 1
a374 2
	    extkey = "TCDLTn";
	    BEGIN(TCCCCn);
d378 6
a383 7
^CROTA	{
	  valtype = FLOAT;
	  vptr = &(wcstem.crota);
	  altlin = 4;
	
	  extkey = "CROTAi";
	  BEGIN(CROTAi);
d386 18
a403 9
^{I1}CROT {
	  valtype = FLOAT;
	  vptr = &(wcstem.crota);
	  altlin = 4;
	
	  sscanf(yytext, "%d", &i);
	
	  extkey = "iCROTn";
	  BEGIN(iCROTn);
d406 7
a412 26
^TCROT	{
	  valtype = FLOAT;
	  vptr = &(wcstem.crota);
	  altlin = 4;
	
	  extkey = "TCROTn";
	  BEGIN(TCROTn);
	}

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

^{I1}CUN  |
^{I1}CUNI {
	  valtype = STRING;
	  vptr = &(wcstem.cunit);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    BEGIN(iCCCna);
d414 1
a414 2
	    extkey = "iCUNIn";
	    BEGIN(iCCCCn);
d418 7
a424 7
^TCUN	|
^TCUNI	{
	  valtype = STRING;
	  vptr = &(wcstem.cunit);
	
	  if (yyleng == 4) {
	    BEGIN(TCCCna);
d426 1
a426 2
	    extkey = "TCUNIn";
	    BEGIN(TCCCCn);
d430 6
a435 6
^CTYPE	{
	  valtype = STRING;
	  vptr = &(wcstem.ctype);
	
	  extkey = "CTYPEia";
	  BEGIN(CCCCCia);
d438 7
a444 9
^{I1}CTY  |
^{I1}CTYP {
	  valtype = STRING;
	  vptr = &(wcstem.ctype);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    BEGIN(iCCCna);
d446 1
a446 2
	    extkey = "iCTYPn";
	    BEGIN(iCCCCn);
d450 7
a456 7
^TCTY	|
^TCTYP	{
	  valtype = STRING;
	  vptr = &(wcstem.ctype);
	
	  if (yyleng == 4) {
	    BEGIN(TCCCna);
d458 1
a458 2
	    extkey = "TCTYPn";
	    BEGIN(TCCCCn);
d462 11
a472 3
^CRVAL	{
	  valtype = FLOAT;
	  vptr = &(wcstem.crval);
d474 3
a476 8
	  extkey = "CRVALia";
	  BEGIN(CCCCCia);
	}

^{I1}CRV  |
^{I1}CRVL {
	  valtype = FLOAT;
	  vptr = &(wcstem.crval);
d478 4
a481 1
	  sscanf(yytext, "%d", &i);
a482 2
	  if (yyleng == 4) {
	    BEGIN(iCCCna);
d484 1
a484 2
	    extkey = "iCRVLn";
	    BEGIN(iCCCCn);
d488 6
a493 11
^TCRV	|
^TCRVL	{
	  valtype = FLOAT;
	  vptr = &(wcstem.crval);
	
	  if (yyleng == 4) {
	    BEGIN(TCCCna);
	  } else {
	    extkey = "TCRVLn";
	    BEGIN(TCCCCn);
	  }
d496 5
a500 5
^LONPOLE |
^LONP	{
	  valtype = FLOAT;
	  vptr = &(wcstem.lonpole);
	
a501 1
	    extkey = "LONPOLEa";
d508 5
a512 5
^LATPOLE |
^LATP	{
	  valtype = FLOAT;
	  vptr = &(wcstem.latpole);
	
a513 1
	    extkey = "LATPOLEa";
d520 6
a525 12
^RESTFRQ  |
^RESTFREQ |
^RFRQ	{
	  valtype = FLOAT;
	  vptr = &(wcstem.restfrq);
	
	  if (yyleng == 8) {
	    extkey = "RESTFREQ";
	    unput(' ');
	    BEGIN(CCCCCCCa);
	  } else if (yyleng == 7) {
	    extkey = "RESTFRQa";
d532 5
a536 5
^RESTWAV |
^RWAV	{
	  valtype = FLOAT;
	  vptr = &(wcstem.restwav);
	
a537 1
	    extkey = "RESTWAVa";
d544 3
a546 4
^PV	{
	  valtype = FLOAT;
	  vptr = &(wcstem.pv);
	  ptype = 'v';
d548 11
a558 9
	  extkey = "PVi_ma";
	  BEGIN(CCi_ma);
	}

^{I1}V	|
^{I1}PV	{
	  valtype = FLOAT;
	  vptr = &(wcstem.pv);
	  ptype = 'v';
d560 4
a563 1
	  sscanf(yytext, "%d", &i);
a564 2
	  if (yyleng == 2) {
	    BEGIN(iCn_ma);
d566 1
a566 2
	    extkey = "iPVn_ma";
	    BEGIN(iCCn_ma);
d570 7
a576 8
^TV	|
^TPV	{
	  valtype = FLOAT;
	  vptr = &(wcstem.pv);
	  ptype = 'v';
	
	  if (yyleng == 2) {
	    BEGIN(TCn_ma);
d578 1
a578 2
	    extkey = "TPVn_ma";
	    BEGIN(TCCn_ma);
d582 10
a591 6
^PROJP	{
	  valtype = FLOAT;
	  vptr = &(wcstem.pv);
	  ptype = 'v';
	
	  BEGIN(PROJPm);
d594 3
a596 4
^PS	{
	  valtype = STRING;
	  vptr = &(wcstem.ps);
	  ptype = 's';
d598 11
a608 9
	  extkey = "PSi_ma";
	  BEGIN(CCi_ma);
	}

^{I1}S	|
^{I1}PS	{
	  valtype = STRING;
	  vptr = &(wcstem.ps);
	  ptype = 's';
d610 3
a612 1
	  sscanf(yytext, "%d", &i);
a613 2
	  if (yyleng == 2) {
	    BEGIN(iCn_ma);
d615 1
a615 2
	    extkey = "iPSn_ma";
	    BEGIN(iCCn_ma);
d619 7
a625 8
^TS	|
^TPS	{
	  valtype = STRING;
	  vptr = &(wcstem.ps);
	  ptype = 's';
	
	  if (yyleng == 2) {
	    BEGIN(TCn_ma);
d627 1
a627 2
	    extkey = "TPSn_ma";
	    BEGIN(TCCn_ma);
d631 10
a640 6
^CNAME	{
	  valtype = STRING;
	  vptr = &(wcstem.cname);
	
	  extkey = "CNAMEia";
	  BEGIN(CCCCCia);
d643 7
a649 9
^{I1}CNA  |
^{I1}CNAM {
	  valtype = STRING;
	  vptr = &(wcstem.cname);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    BEGIN(iCCCna);
d651 1
a651 9
	    if (relax & WCSHDR_CNAMn) {
	      extkey = "iCNAMn";
	      BEGIN(iCCCCn);
	    } else if (relax & WCSHDR_reject) {
	      errmsg = "iCNAMn keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d655 6
a660 127
^TCNA	|
^TCNAM	{
	  valtype = STRING;
	  vptr = &(wcstem.cname);
	
	  if (yyleng == 4) {
	    BEGIN(TCCCna);
	  } else {
	    if (relax & WCSHDR_CNAMn) {
	      extkey = "TCNAMn";
	      BEGIN(TCCCCn);
	    } else if (relax & WCSHDR_reject) {
	      errmsg = "TCNAMn keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  }
	}

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

^{I1}CRD |
^{I1}CRDE {
	  valtype = FLOAT;
	  vptr = &(wcstem.crder);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    BEGIN(iCCCna);
	  } else {
	    if (relax & WCSHDR_CNAMn) {
	      extkey = "iCRDEn";
	      BEGIN(iCCCCn);
	    } else if (relax & WCSHDR_reject) {
	      errmsg = "iCRDEn keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  }
	}

^TCRD	|
^TCRDE	{
	  valtype = FLOAT;
	  vptr = &(wcstem.crder);
	
	  if (yyleng == 4) {
	    BEGIN(TCCCna);
	  } else {
	    if (relax & WCSHDR_CNAMn) {
	      extkey = "TCRDEn";
	      BEGIN(TCCCCn);
	    } else if (relax & WCSHDR_reject) {
	      errmsg = "TCRDEn keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  }
	}

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

^{I1}CSY  |
^{I1}CSYE {
	  valtype = FLOAT;
	  vptr = &(wcstem.csyer);
	
	  sscanf(yytext, "%d", &i);
	
	  if (yyleng == 4) {
	    BEGIN(iCCCna);
	  } else {
	    if (relax & WCSHDR_CNAMn) {
	      extkey = "iCSYEn";
	      BEGIN(iCCCCn);
	    } else if (relax & WCSHDR_reject) {
	      errmsg = "iCSYEn keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  }
	}

^TCSY	|
^TCSYE	{
	  valtype = FLOAT;
	  vptr = &(wcstem.csyer);
	
	  if (yyleng == 4) {
	    BEGIN(TCCCna);
	  } else {
	    if (relax & WCSHDR_CNAMn) {
	      extkey = "TCSYEn";
	      BEGIN(TCCCCn);
	    } else if (relax & WCSHDR_reject) {
	      errmsg = "TCSYEn keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  }
	}

^DATE-AVG |
^DAVG   {
	  valtype = STRING;
	  vptr = wcstem.dateavg;
	
	  if (yyleng == 8) {
	    extkey = "DATE-AVG";
d663 1
a663 62
	    BEGIN(CCCCn);
	  }
	}

^DATE-OBS {
	  valtype = STRING;
	  vptr = wcstem.dateobs;
	
	  extkey = "DATE-OBS";
	  BEGIN(CCCCCCCC);
	}

^DOBS{I1}"   " |
^DOBS{I2}"  "  |
^DOBS{I3}" " {
	  if (relax & WCSHDR_DOBSn) {
	    valtype = STRING;
	    vptr = wcstem.dateobs;
	
	    yyless(4);
	    BEGIN(CCCCn);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "DOBSna keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

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

^EQUINOX |
^EQUI	{
	  valtype = FLOAT;
	  vptr = &(wcstem.equinox);
	
	  if (yyleng == 7) {
	    extkey = "EQUINOXa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
d667 5
a671 18
^MJD-AVG" " |
^MJDA	{
	  valtype = FLOAT;
	  vptr = &(wcstem.mjdavg);
	
	  if (yyleng == 8) {
	    extkey = "MJD-AVG";
	    BEGIN(CCCCCCCC);
	  } else {
	    BEGIN(CCCCn);
	  }
	}

^MJD-OBS" " |
^MJDOB	{
	  valtype = FLOAT;
	  vptr = &(wcstem.mjdobs);
	
a672 1
	    extkey = "MJD-OBS";
d679 5
a683 5
^OBSGEO-X |
^OBSGX	{
	  valtype = FLOAT;
	  vptr = wcstem.obsgeo;
	
a684 1
	    extkey = "OBSGEO-X";
d691 5
a695 5
^OBSGEO-Y |
^OBSGY	{
	  valtype = FLOAT;
	  vptr = wcstem.obsgeo + 1;
	
a696 1
	    extkey = "OBSGEO-Y";
d703 5
a707 5
^OBSGEO-Z |
^OBSGZ	{
	  valtype = FLOAT;
	  vptr = wcstem.obsgeo + 2;
	
a708 1
	    extkey = "OBSGEO-Z";
a714 189
^RADESYS |
^RADE	{
	  valtype = STRING;
	  vptr = wcstem.radesys;
	
	  if (yyleng == 7) {
	    extkey = "RADESYSa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^RADECSYS {
	  if (relax & WCSHDR_RADECSYS) {
	    valtype = STRING;
	    vptr = wcstem.radesys;
	
	    unput(' ');
	    extkey = "RADECSYS";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "RADECSYS keyword is non-standard";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^SPECSYS |
^SPEC	{
	  valtype = STRING;
	  vptr = wcstem.specsys;
	
	  if (yyleng == 7) {
	    extkey = "SPECSYSa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^SSYSOBS |
^SOBS	{
	  valtype = STRING;
	  vptr = wcstem.ssysobs;
	
	  if (yyleng == 7) {
	    extkey = "SSYSOBSa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^SSYSSRC |
^SSRC	{
	  valtype = STRING;
	  vptr = wcstem.ssyssrc;
	
	  if (yyleng == 7) {
	    extkey = "SSYSSRCa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^VELOSYS |
^VSYS	{
	  valtype = FLOAT;
	  vptr = &(wcstem.velosys);
	
	  if (yyleng == 7) {
	    extkey = "VELOSYSa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^VELANGL |
^VANG	{
	  valtype = FLOAT;
	  vptr = &(wcstem.velangl);
	
	  if (yyleng == 7) {
	    extkey = "VELANGLa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^VELREF{ALT}" " {
	  sscanf(yytext, "VELREF%c", &a);
	
	  if (a == ' ' || (relax & WCSHDR_VELREFa)) {
	    valtype = INTEGER;
	    vptr = wcstem.specsys;
	    special = wcsbth_velref;
	
	    unput(a);
	    extkey = "VELREF";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VELREF keyword may not have an alternate version code";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^VSOURCE{ALT} {
	  sscanf(yytext, "VSOURCE%c", &a);
	
	  if (relax & WCSHDR_VSOURCEa) {
	    valtype = FLOAT;
	    vptr = &(wcstem.zsource);
	    special = wcsbth_vsource;
	
	    unput(a);
	    extkey = "VSOURCEa";
	    BEGIN(CCCCCCCa);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VSOURCEa keyword is deprecated";
	    BEGIN(ERROR);
	
	  } else {
	    BEGIN(DISCARD);
	  }
	}

^VSOU{I1}{ALT}"  " |
^VSOU{I2}{ALT}" "  |
^VSOU{I3}{ALT} {
	  sscanf(yytext, "VSOU%d%c", &n, &a);
	
	  if (relax & WCSHDR_VSOURCEa) {
	    valtype = FLOAT;
	    vptr = &(wcstem.zsource);
	    special = wcsbth_vsource;
	
	    yyless(4);
	    BEGIN(CCCCna);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "VSOUna keyword is deprecated";
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

^WCSNAME |
^WCSN |
^TWCS	{
	  /* ::: WCSHDR_WCSNna */
	  valtype = STRING;
	  vptr = wcstem.wcsname;
	
	  if (yyleng == 7) {
	    extkey = "WCSNAMEa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

^ZSOURCE |
^ZSOU	{
	  valtype = FLOAT;
	  vptr = &(wcstem.zsource);
	
	  if (yyleng == 7) {
	    extkey = "ZSOURCEa";
	    BEGIN(CCCCCCCa);
	  } else {
	    BEGIN(CCCCna);
	  }
	}

d716 1
d719 1
a719 1
	    errmsg = "Illegal keyrecords following END keyrecord";
d727 1
d732 9
a740 6
<CCCCCia>{I1}{ALT}" " |
<CCCCCia>{I2}{ALT} {
	  /* Image-header keyword. */
	  if (relax & WCSHDR_ALLIMG) {
	    sscanf(yytext, "%d%c", &i, &a);
	    keytype = IMGAXIS;
d744 2
a745 3
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "Image-header keyword %s in binary table", extkey);
a748 1
	    /* Pretend we don't recognize it. */
d753 7
a759 10
<CCCCCia>{I3} {
	  /* Invalid axis number in image-header keyword. */
	  if (relax & WCSHDR_ALLIMG) {
	    /* Will be flagged by <VALUE> as invalid. */
	    sscanf(yytext, "%3d", &i);
	    BEGIN(VALUE);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
a760 46
	}

<iCCCCn>{I1}"  " |
<iCCCCn>{I2}" "  |
<iCCCCn>{I3}     |
<TCCCCn>{I1}"  " |
<TCCCCn>{I2}" "  |
<TCCCCn>{I3} {
	  WCSBTH_PUTBACK;
	  BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
	}

<iCCCCn>{I1}[A-Z]" " |
<iCCCCn>{I2}[A-Z]    |
<TCCCCn>{I1}[A-Z]" " |
<TCCCCn>{I2}[A-Z] {
	  if (relax & WCSHDR_LONGKEY) {
	    WCSBTH_PUTBACK;
	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "%s keyword may not have an alternate version code", extkey);
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<iCCCCn>. |
<TCCCCn>. {
	  BEGIN(DISCARD);
	}

<iCCCna>{I1}{ALT}"  " |
<iCCCna>{I2}{ALT}" "  |
<iCCCna>{I3}{ALT}     |
<TCCCna>{I1}{ALT}"  " |
<TCCCna>{I2}{ALT}" "  |
<TCCCna>{I3}{ALT} {
	  sscanf(yytext, "%d%c", &n, &a);
	  if (YY_START == TCCCna) i = wcsbth_colax(*wcs, &alts, n, a);
	  keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
d764 2
a765 2
<iCCCna>. |
<TCCCna>. {
d769 5
a773 45
<CCi_ja>{I1}_{I1}{ALT}"  " |
<CCi_ja>{I1}_{I2}{ALT}" " |
<CCi_ja>{I2}_{I1}{ALT}" " |
<CCi_ja>{I2}_{I2}{ALT} {
	  /* Image-header keyword. */
	  if (relax & WCSHDR_ALLIMG) {
	    sscanf(yytext, "%d_%d%c", &i, &j, &a);
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "Image-header keyword %s in binary table", extkey);
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<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 number in image-header keyword. */
	  if (relax & WCSHDR_ALLIMG) {
	    /* Will be flagged by <VALUE> as invalid. */
	    sscanf(yytext, "%d_%d", &i, &j);
	    BEGIN(VALUE);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<CCi_ja>{I0}{6} {
	  /* This covers the defunct forms CD00i00j and PC00i00j. */
	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
	    sscanf(yytext, "%3d%3d", &i, &j);
d775 1
a775 1
	    keytype = IMGAXIS;
d779 1
a779 3
	    errmsg = errtxt;
	    sprintf(errmsg, "Defunct form of %si_ja keyword",
	                     (altlin==1) ? "PC" : "CD");
a782 1
	    /* Pretend we don't recognize it. */
d787 2
a788 1
<CCi_ja>. {
d792 3
a794 3
<ijCCna>{I1}{ALT}"  " |
<ijCCna>{I2}{ALT}" "  |
<ijCCna>{I3}{ALT} {
a795 3
	  keytype = BIMGARR;
	  BEGIN(VALUE);
	}
d797 6
a802 24
<TCCn_ka>{I1}_{I1}{ALT}" " |
<TCCn_ka>{I1}_{I2}{ALT} |
<TCCn_ka>{I2}_{I1}{ALT} |
<TCCn_ka>{I1}_{I3} |
<TCCn_ka>{I2}_{I2} |
<TCCn_ka>{I3}_{I1} {
	  if (relax & WCSHDR_LONGKEY) {
	    WCSBTH_PUTBACK;
	    BEGIN(TCn_ka);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg, "%s keyword is non-standard", extkey);
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<TCCn_ka>. {
	  BEGIN(DISCARD);
	}
a803 41
<TCn_ka>{I1}_{I1}{ALT}"  " |
<TCn_ka>{I1}_{I2}{ALT}" " |
<TCn_ka>{I2}_{I1}{ALT}" " |
<TCn_ka>{I1}_{I3}{ALT} |
<TCn_ka>{I2}_{I2}{ALT} |
<TCn_ka>{I3}_{I1}{ALT} {
	  sscanf(yytext, "%d_%d%c", &n, &k, &a);
	  i = wcsbth_colax(*wcs, &alts, n, a);
	  j = wcsbth_colax(*wcs, &alts, k, a);
	  keytype = PIXLIST;
	  BEGIN(VALUE);
	}

<TCn_ka>{I1}_{I4} |
<TCn_ka>{I2}_{I3} |
<TCn_ka>{I3}_{I2} |
<TCn_ka>{I4}_{I1} {
	  sscanf(yytext, "%d_%d", &n, &k);
	  a = ' ';
	  i = wcsbth_colax(*wcs, &alts, n, a);
	  j = wcsbth_colax(*wcs, &alts, k, a);
	  keytype = PIXLIST;
	  BEGIN(VALUE);
	}

<TCn_ka>. {
	  BEGIN(DISCARD);
	}

<CROTAi>{I1}"  " |
<CROTAi>{I2}" " {
	  yyless(0);
	  BEGIN(CCCCCia);
	}

<CROTAi>{I1}[A-Z]" " |
<CROTAi>{I2}[A-Z] {
	  if (relax & WCSHDR_CROTAia) {
	    yyless(0);
	    BEGIN(CCCCCia);
	
d805 1
a805 1
	    errmsg = "CROTAn keyword may not have an alternate version code";
a806 6
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}
a807 28
<CROTAi>. {
	  BEGIN(DISCARD);
	}

<iCROTn>{I1}"  " |
<iCROTn>{I2}" "  |
<iCROTn>{I3}     |
<TCROTn>{I1}"  " |
<TCROTn>{I2}" "  |
<TCROTn>{I3} {
	  WCSBTH_PUTBACK;
	  BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
	}

<iCROTn>{I1}[A-Z]" " |
<iCROTn>{I2}[A-Z]    |
<TCROTn>{I1}[A-Z]" " |
<TCROTn>{I2}[A-Z] {
	  if (relax & WCSHDR_CROTAia) {
	    WCSBTH_PUTBACK;
	    BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "%s keyword may not have an alternate version code", extkey);
	    BEGIN(ERROR);
	
a808 1
	    /* Pretend we don't recognize it. */
d813 2
a814 45
<iCROTn>. |
<TCROTn>. {
	  BEGIN(DISCARD);
	}

<CCCCCCCa>{ALT} |
<CCCCCCCC>. {
	  /* Image-header keyword. */
	  if (relax & (WCSHDR_AUXIMG | WCSHDR_ALLIMG)) {
	    if (YY_START == CCCCCCCa) {
	      sscanf(yytext, "%c", &a);
	    } else {
	      a = 0;
	      unput(yytext[0]);
	    }
	    keytype = IMGAUX;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "Image-header keyword %s in binary table", extkey);
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
	}

<CCCCCCCa>. {
	  BEGIN(DISCARD);
	}

<CCCCna>{I1}{ALT}"  " |
<CCCCna>{I2}{ALT}" "  |
<CCCCna>{I3}{ALT}     |
<CCCCCna>{I1}{ALT}" " |
<CCCCCna>{I2}{ALT} {
	  sscanf(yytext, "%d%c", &n, &a);
	  keytype = BINTAB;
	  BEGIN(VALUE);
	}

<CCCCCna>{I3} {
d817 4
a820 1
	  keytype = BINTAB;
d824 9
a832 3
<CCCCna>. |
<CCCCCna>. {
	  BEGIN(DISCARD);
d835 8
a842 10
<CCCCn>{I1}"   " |
<CCCCn>{I2}"  "  |
<CCCCn>{I3}" "   |
<CCCCn>{I4}      |
<CCCCCn>{I1}"  " |
<CCCCCn>{I2}" "  |
<CCCCCn>{I3} {
	  sscanf(yytext, "%d", &n);
	  a = 0;
	  keytype = BINTAB;
d846 2
a847 2
<CCCCn>. |
<CCCCCn>. {
d851 16
a866 15
<CCi_ma>{I1}_{I0}{ALT}"  " |
<CCi_ma>{I1}_{I2}{ALT}" " |
<CCi_ma>{I2}_{I0}{ALT}" " |
<CCi_ma>{I2}_{I2}{ALT} {
	  /* Image-header keyword. */
	  if (relax & WCSHDR_ALLIMG) {
	    sscanf(yytext, "%d_%d%c", &i, &m, &a);
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg,
	      "Image-header keyword %s in binary table", extkey);
	    BEGIN(ERROR);
d868 3
a870 3
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
d872 1
d875 14
a888 15
<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 parameter in image-header keyword. */
	  if (relax & WCSHDR_ALLIMG) {
	    /* Will be flagged by <VALUE> as invalid. */
	    sscanf(yytext, "%d_%d", &i, &m);
	    BEGIN(VALUE);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
d890 1
d893 3
a895 1
<CCi_ma>. {
d899 14
a912 24
<iCCn_ma>{I1}_{I0}{ALT}" " |
<iCCn_ma>{I1}_{I2}{ALT}    |
<iCCn_ma>{I1}_{I3}         |
<iCCn_ma>{I2}_{I0}{ALT}    |
<iCCn_ma>{I2}_{I2}         |
<iCCn_ma>{I3}_{I0}         |
<TCCn_ma>{I1}_{I0}{ALT}" " |
<TCCn_ma>{I1}_{I2}{ALT}    |
<TCCn_ma>{I1}_{I3}         |
<TCCn_ma>{I2}_{I0}{ALT}    |
<TCCn_ma>{I2}_{I2}         |
<TCCn_ma>{I3}_{I0} {
	  if (relax & WCSHDR_LONGKEY) {
	    WCSBTH_PUTBACK;
	    BEGIN((YY_START == iCCn_ma) ? iCn_ma : TCn_ma);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = errtxt;
	    sprintf(errmsg, "%s keyword is non-standard", extkey);
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
a913 22
	}

<iCCn_ma>. |
<TCCn_ma>. {
	  BEGIN(DISCARD);
	}

<iCn_ma>{I1}_{I0}{ALT}"  " |
<iCn_ma>{I1}_{I2}{ALT}" "  |
<iCn_ma>{I1}_{I3}{ALT}     |
<iCn_ma>{I2}_{I0}{ALT}" "  |
<iCn_ma>{I2}_{I2}{ALT}     |
<iCn_ma>{I3}_{I0}{ALT}     |
<TCn_ma>{I1}_{I0}{ALT}"  " |
<TCn_ma>{I1}_{I2}{ALT}" "  |
<TCn_ma>{I1}_{I3}{ALT}     |
<TCn_ma>{I2}_{I0}{ALT}" "  |
<TCn_ma>{I2}_{I2}{ALT}     |
<TCn_ma>{I3}_{I0}{ALT} {
	  sscanf(yytext, "%d_%d%c", &n, &m, &a);
	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
d917 8
a924 9
<iCn_ma>{I1}_{I4} |
<iCn_ma>{I2}_{I3} |
<iCn_ma>{I3}_{I2} |
<iCn_ma>{I4}_{I0} |
<TCn_ma>{I1}_{I4} |
<TCn_ma>{I2}_{I3} |
<TCn_ma>{I3}_{I2} |
<TCn_ma>{I4}_{I0} {
	  /* Invalid combinations will be flagged by <VALUE>. */
d927 4
a930 2
	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
d934 3
a936 2
<iCn_ma>. |
<TCn_ma>. {
d940 5
a944 16
<PROJPm>{I0}"  " {
	  if (relax & WCSHDR_PROJPn) {
	    sscanf(yytext, "%d", &m);
	    i = 0;
	    a = ' ';
	    keytype = IMGAXIS;
	    BEGIN(VALUE);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "PROJPn keyword is defunct";
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
	  }
d947 2
a948 1
<PROJPm>. {
d952 8
d961 7
a967 44
	  /* Do checks on i, m, n, k. */
	  if (i > 99 || j > 99 || m > 99 || n > 999 || k > 999) {
	    if (relax & WCSHDR_reject) {
	      errmsg = errtxt;
	      if (i > 99 || j > 99) {
	        sprintf(errmsg, "Axis number exceeds 9");
	      } else if (m > 99) {
	        sprintf(errmsg, "Parameter number exceeds 99");
	      } else if (n > 999 || k > 999) {
	        sprintf(errmsg, "Column number exceeds 999");
	      }
	      BEGIN(ERROR);
	
	    } else {
	      /* Pretend we don't recognize it. */
	      BEGIN(DISCARD);
	    }
	
	  } else if (ipass == 2 && npass == 3 && keytype & BINTAB) {
	    /* Skip keyvalues that won't be inherited. */
	    BEGIN(FLUSH);
	
	  } else if (ipass == 3 && keytype & IMGHEAD) {
	    /* IMGHEAD keytypes are always dealt with on the second pass. */
	    BEGIN(FLUSH);
	
	  } else if (vptr) {
	    alts.icol = 0;
	    alts.iax  = 0;
	    voff = (char *)vptr - (char *)(&wcstem);
	
	    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);
	    }
	
d969 1
a969 1
	    errmsg = "Internal parser ERROR, null pointer";
d975 2
a976 1
	  errmsg = "Invalid KEYWORD = VALUE syntax";
d981 3
a983 4
	  if (ipass == 1) {
	    /* Do first-pass bookkeeping. */
	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
	    if (alts.imgherit) npass = 3;
d985 1
a985 1

d987 21
a1007 8
	    /* Update each coordinate representation. */
	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
	      wptr = (void *)((char *)wcsp + voff);
	
	      /* Read the keyvalue. */
	      if (special) {
	        special(wptr);
	      } else {
d1009 2
d1012 6
a1018 2
	
	    BEGIN(COMMENT);
d1023 2
a1024 1
	  errmsg = "An integer value was expected";
d1029 3
a1031 4
	  if (ipass == 1) {
	    /* Do first-pass bookkeeping. */
	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
	    if (alts.imgherit) npass = 3;
d1033 1
a1033 1

d1035 14
a1048 14
	    /* Update each coordinate representation. */
	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
	      wptr = (void *)((char *)wcsp + voff);
	
	      /* Apply keyword parameterization. */
	      if (ptype == 'v') {
	        ipx = wcsp->npv++;
	        wcsp->pv[ipx].i = i;
	        wcsp->pv[ipx].m = m;
	        wptr = &(wcsp->pv[ipx].value);
	
	      } else if (j) {
	        /* ::: Is the de-reference necessary? */
	        wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis) + (j - 1);
d1050 10
a1059 3
	      } else if (i) {
	        wptr = *((double **)wptr) + (i - 1);
	      }
d1061 1
a1061 4
	      /* Read the keyvalue. */
	      if (special) {
	        special(wptr);
	      } else {
d1063 8
d1073 5
a1077 5
	      /* Flag the presence of PC, or CD and/or CROTA. */
	      if (altlin) {
	        wcsp->altlin |= altlin;
	        altlin = 0;
	      }
a1078 2
	
	    BEGIN(COMMENT);
d1083 2
a1084 1
	  errmsg = "A floating-point value was expected";
d1089 3
a1091 4
	  if (ipass == 1) {
	    /* Do first-pass bookkeeping. */
	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
	    if (alts.imgherit) npass = 3;
d1095 8
a1102 14
	    /* Update each coordinate representation. */
	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
	      wptr = (void *)((char *)wcsp + voff);
	
	      /* Apply keyword parameterization. */
	      if (ptype == 's') {
	        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);
d1104 5
a1108 3
	      } else if (i) {
	        wptr = *((char (**)[72])wptr) + (i - 1);
	      }
d1110 9
a1118 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];
d1121 19
a1139 5
	        if (cptr[jx] == '\0') {
	          if (ix) cptr[ix-1] = '\0';
	          break;
	        } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
	          jx++;
d1142 1
a1142 1
	        ix++;
d1144 6
a1150 2
	
	    BEGIN(COMMENT);
d1155 2
a1156 1
	  errmsg = "A string value was expected";
d1162 1
d1167 2
a1168 1
	  errmsg = "Malformed inline comment";
d1173 2
a1174 1
	  if (ipass == npass) {
a1185 1
	
d1190 1
d1192 1
a1192 1
	  if (ipass == npass) {
a1205 1
	
d1210 2
a1211 3
	  i = j = 0;
	  n = k = 0;
	  m = 0;
d1213 1
a1213 5
	
	  keytype =  0;
	  valtype = -1;
	  vptr    = 0x0;
	
d1215 1
a1215 2
	  ptype  = ' ';
	  special = 0x0;
d1220 4
a1223 3
	  /* End-of-input. */
	  if (ipass == 1) {
	    if ((status = wcsbth_init1(&alts, nwcs, wcs)) || *nwcs == 0) {
a1235 1
	  }
a1236 1
	  if (ipass++ < npass) {
d1241 2
a1242 3
	    i = j = 0;
	    k = n = 0;
	    m = 0;
d1244 1
d1246 1
a1246 7
	    keytype =  0;
	    valtype = -1;
	    vptr    = 0x0;
	
	    altlin = 0;
	    ptype  = ' ';
	    special = 0x0;
a1247 2
	    yyrestart(yyin);
	    
d1255 1
a1255 1
	    status = wcsbth_final(&alts, nwcs, wcs);
d1264 3
a1266 23
*   Perform first-pass tasks:
*
*   1) Count the number of coordinate axes in each of the 27 possible
*      alternate image-header coordinate representations.  Also count the
*      number of PVi_ma and PSi_ma keywords in each representation.
*
*   2) Determine the number of binary table columns that have an image array
*      with a coordinate representation (up to 999), and count the number of
*      coordinate axes in each of the 27 possible alternates.  Also count the
*      number of iVn_ma and iSn_ma keywords in each representation.
*
*   3) Determine the number of alternate pixel list coordinate representations
*      (up to 27) and the table columns associated with each.  Also count the
*      number of TVn_ma and TSn_ma keywords in each representation.
*
*   In the first pass alts->arridx[icol][27] is used to determine the number
*   of axes in each of 27 possible image-header coordinate descriptions
*   (icol == 0) and each of the 27 possible coordinate representations for an
*   image array in each column.
*
*   The elements of alts->pixlist[icol] are used as bit arrays to flag which
*   of the 27 possible pixel list coordinate representations are associated
*   each table column.
d1269 1
a1269 9
int wcsbth_pass1(
  int keytype,
  int i,
  int j,
  int n,
  int k,
  char a,
  char ptype,
  struct wcsbth_alts *alts)
d1272 8
a1279 53
  int iax, icol, mask, ncol;

  if (a == 0) {
    /* Keywords such as DATE-OBS go along for the ride. */
    return 0;
  }

  ncol = alts->ncol;

  /* Do we need to allocate memory for alts? */
  if (alts->arridx == 0x0) {
    if (ncol == 0) {
      /* Can only happen if TFIELDS is missing or out-of-sequence.  If n and
         k are both zero then we may be processing an image header so leave
         ncol alone - the array will be realloc'd later if required. */
      if (n || k) {
        /* The header is mangled, assume the worst. */
        ncol = 999;
      }
    }

    if (!(alts->arridx  =  calloc((1 + ncol)*27, sizeof(short int))) ||
        !(alts->npv     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
        !(alts->nps     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
        !(alts->pixlist =  calloc((1 + ncol),    sizeof(unsigned int)))) {
      return 2;
    }

    alts->ncol = ncol;

  } else if (n > ncol || k > ncol) {
    /* Can only happen if TFIELDS or the WCS keyword is wrong; carry on. */
    ncol = 999;
    if (!(alts->arridx  = realloc(alts->arridx,
                                    27*(1 + ncol)*sizeof(short int))) ||
        !(alts->npv     = realloc(alts->npv,
                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
        !(alts->nps     = realloc(alts->nps,
                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
        !(alts->pixlist = realloc(alts->pixlist,
                                       (1 + ncol)*sizeof(unsigned int)))) {
      return 2;
    }

    /* Since realloc() doesn't initialize the extra memory. */
    for (icol = (1 + alts->ncol); icol < (1 + ncol); icol++) {
      for (iax = 0; iax < 27; iax++) {
        alts->arridx[icol][iax] = 0;
        alts->npv[icol][iax] = 0;
        alts->nps[icol][iax] = 0;
        alts->pixlist[icol]  = 0;
      }
    }
d1281 1
a1281 2
    alts->ncol = ncol;
  }
d1288 1
a1288 9
  /* A BINTAB keytype such as LONPna, in conjunction with an IMGAXIS keytype
     causes a table column to be recognized as an image array. */
  if (keytype & IMGHEAD || keytype & BIMGARR) {
    /* n == 0 is expected for IMGHEAD keywords. */
    if (i == 0 && j == 0) {
      if (alts->arridx[n][iax] == 0) {
        /* Flag that an auxiliary keyword was seen. */
        alts->arridx[n][iax] = -1;
      }
d1290 1
a1290 5
    } else {
      /* Record the maximum axis number found. */
      if (alts->arridx[n][iax] < i) {
        alts->arridx[n][iax] = i;
      }
d1292 3
a1294 4
      if (alts->arridx[n][iax] < j) {
        alts->arridx[n][iax] = j;
      }
    }
d1296 2
a1297 5
    if (ptype == 'v') {
      alts->npv[n][iax]++;
    } else if (ptype == 's') {
      alts->nps[n][iax]++;
    }
d1299 3
a1301 19
  
  /* BINTAB keytypes, which apply both to pixel lists as well as binary table
     image arrays, never contribute to recognizing a table column as a pixel
     list axis.  A PIXLIST keytype is required for that. */
  if (keytype == PIXLIST) {
    mask = 1 << iax;

    /* n > 0 for PIXLIST keytypes. */
    alts->pixlist[n] |= mask;
    if (k) alts->pixlist[k] |= mask;

    /* Used as a flag over all columns. */
    alts->pixlist[0] |= mask;

    if (ptype == 'v') {
      alts->pixnpv[iax]++;
    } else if (ptype == 's') {
      alts->pixnps[iax]++;
    }
a1302 2

  return 0;
d1307 2
a1308 5
*   Perform initializations at the end of the first pass:
*
*   1) Determine the required number of wcsprm structs, allocate memory for
*      an array of them and initialize each one.
*
d1311 4
a1314 2
int wcsbth_init1(
  struct wcsbth_alts *alts,
d1316 2
a1317 1
  struct wcsprm **wcs)
d1320 1
a1320 1
  int iax, icol, inherit[27], ix, mask, ncol, npsmax, npvmax, status = 0;
d1323 1
a1323 21

  if (alts->arridx == 0x0) {
    *nwcs = 0;
    return 0;
  }

  /* Determine the number of axes in each pixel list representation. */
  ncol = alts->ncol;
  for (iax = 0, mask = 1; iax < 27; iax++, mask <<= 1) {
    alts->pixidx[iax] = 0;

    if (alts->pixlist[0] | mask) {
      for (icol = 1; icol <= ncol; icol++) {
        if (alts->pixlist[icol] & mask) {
          alts->pixidx[iax]++;
        }
      }
    }
  }

  /* Find the total number of coordinate representations. */
a1324 1
  alts->imgherit = 0;
d1326 1
a1326 42
    inherit[iax] = 0;

    for (icol = 1; icol <= ncol; icol++) {
      if (alts->arridx[icol][iax] < 0) {
        /* No BIMGARR keytype but there's at least one BINTAB. */
        if (alts->arridx[0][iax] > 0) {
          /* There is an IMGAXIS keytype that we will inherit, so count this
	     representation. */
          alts->arridx[icol][iax] = alts->arridx[0][iax];
        } else {
          alts->arridx[icol][iax] = 0;
        }
      }

      if (alts->arridx[icol][iax]) {
        if (alts->arridx[0][iax]) {
          /* All IMGHEAD keywords are inherited for this iax. */
          inherit[iax] = 1;

          if (alts->arridx[icol][iax] < alts->arridx[0][iax]) {
            /* The extra axes are also inherited. */
            alts->arridx[icol][iax] = alts->arridx[0][iax];
          }
        }

        (*nwcs)++;
      }
    }

    /* Count every "a" found in any IMGHEAD keyword... */
    if (alts->arridx[0][iax]) {
      if (inherit[iax]) {
        /* ...but not if the IMGHEAD keywords will be inherited. */
        alts->arridx[0][iax] = 0;
        alts->imgherit = 1;
      } else {
        (*nwcs)++;
      }
    }

    /* We need a struct for every "a" found in a PIXLIST keyword. */
    if (alts->pixidx[iax]) {
a1330 1

d1341 8
a1348 19
    /* Initialize each wcsprm struct. */
    wcsp = *wcs;
    *nwcs = 0;
    for (icol = 0; icol <= ncol; icol++) {
      for (iax = 0; iax < 27; iax++) {
        if (alts->arridx[icol][iax]) {
          /* Image-header representations that are not for inheritance
             (icol == 0) or binary table image array representations. */
          wcsp->flag = -1;
          wcsnpv(alts->npv[icol][iax]);
          wcsnps(alts->nps[icol][iax]);
          if ((status = wcsini(1, (int)(alts->arridx[icol][iax]), wcsp))) {
            wcsvfree(nwcs, wcs);
            break;
          }

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

          /* Record the table column number. */
          wcsp->colnum = icol;

          /* On the second pass alts->arridx[icol][27] indexes the array of
             wcsprm structs. */
          alts->arridx[icol][iax] = (*nwcs)++;

          wcsp++;

        } else {
          /* Signal that this column has no WCS for this "a". */
          alts->arridx[icol][iax] = -1;
d1354 3
d1358 1
a1358 2
      if (alts->pixidx[iax]) {
        /* Pixel lists representations. */
d1360 3
a1362 3
        wcsnpv(alts->pixnpv[iax]);
        wcsnps(alts->pixnps[iax]);
        if ((status = wcsini(1, (int)(alts->pixidx[iax]), wcsp))) {
d1372 1
a1372 1
        /* Record the pixel list column numbers. */
d1374 2
a1375 2
        for (icol = 1, ix = 0; icol <= ncol; icol++) {
          if (alts->pixlist[icol] & mask) {
d1380 2
a1381 2
        /* alts->pixidx[] indexes the array of wcsprm structs. */
        alts->pixidx[iax] = (*nwcs)++;
a1383 4

      } else {
        /* Signal that this column is not a pixel list axis for this "a". */
        alts->pixidx[iax] = -1;
a1396 48
*   Return a pointer to the next wcsprm struct for a particular column number
*   and alternate.
*---------------------------------------------------------------------------*/

struct wcsprm *wcsbth_idx(
  struct wcsprm *wcs,
  struct wcsbth_alts *alts,
  int  keytype,
  int  n,
  char a)

{
  const char as[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  int iwcs;

  if (!wcs) return 0x0;

  iwcs = -1;
  for (; iwcs < 0 && alts->iax < 27; alts->iax++) {
    /* Note that a == 0 applies to every alternate, otherwise this
       loop simply determines the appropriate value of alts->iax. */
    if (a && a != as[alts->iax]) continue;

    if (keytype & (IMGHEAD | BIMGARR)) {
      for (; iwcs < 0 && alts->icol <= alts->ncol; alts->icol++) {
        /* Image header keywords, n == 0, apply to all columns, otherwise this
           loop simply determines the appropriate value of alts->icol. */
        if (n && n != alts->icol) continue;
        iwcs = alts->arridx[alts->icol][alts->iax];
      }

      /* Break out of the loop to stop alts->iax from being incremented. */
      if (iwcs >= 0) break;

      /* Start from scratch for the next alts->iax. */
      alts->icol = 0;
    }

    if (keytype & (IMGAUX | PIXLIST)) {
      iwcs = alts->pixidx[alts->iax];
    }
  }

  return (iwcs >= 0) ? (wcs + iwcs) : 0x0;
}


/*----------------------------------------------------------------------------
d1398 1
a1398 1
*   particular pixel list coordinate representation.
d1401 1
a1401 5
int wcsbth_colax(
  struct wcsprm *wcs,
  struct wcsbth_alts *alts,
  int n,
  char a)
d1407 1
a1407 3
  if (!wcs) return 0;

  wcsp = wcs;
d1409 1
a1409 1
    wcsp += alts->pixidx[a-'A'+1];
d1423 2
a1424 1
*   Interpret EPOCH keywords.
d1427 7
a1433 1
int wcsbth_epoch(void *wptr)
d1436 4
a1439 1
  double *equinox;
d1441 6
a1446 8
  /* If EQUINOXa is currently undefined then set it from EPOCHa. */
  equinox = (double *)wptr;
  if (undefined(*equinox)) {
    sscanf(yytext, "%lf", equinox);
  }

  return 0;
}
d1448 10
d1459 5
a1463 19
/*----------------------------------------------------------------------------
*   Interpret VELREF keywords.
*---------------------------------------------------------------------------*/

int wcsbth_velref(void *wptr)

{
  const char *frames[] = {"LSRK", "BARYCENT", "TOPOCENT",
                          "LSRD", "GEOCENTR", "SOURCE", "GALACTOC"};
  char *specsys;
  int ivf, velref;

  /* If SPECSYSa is currently undefined then set it from VELREF. */
  specsys = (char *)wptr;
  if (specsys[0] == '\0') {
    sscanf(yytext, "%lf", &velref);
    ivf = velref%256 - 1;
    if (0 <= ivf && ivf < 7) {
      sprintf(specsys, "%s", frames[ivf]);
a1464 14
  }

  return 0;
}


/*----------------------------------------------------------------------------
*   Interpret VSOURCE keywords.
*---------------------------------------------------------------------------*/

int wcsbth_vsource(void *wptr)

{
  double beta, c = 299792458.0, vsource, *zsource;
a1465 27
  /* If ZSOURCEa is currently undefined then set it from VSOURCEa. */
  zsource = (double *)wptr;
  if (undefined(*zsource)) {
    sscanf(yytext, "%lf", &vsource);

    /* Convert relativistic Doppler velocity to redshift. */
    beta = vsource/c;
    *zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
  }

  return 0;
}


/*----------------------------------------------------------------------------
*   Tie up loose ends.
*---------------------------------------------------------------------------*/

int wcsbth_final(
  struct wcsbth_alts *alts,
  int *nwcs,
  struct wcsprm **wcs)

{
  int iax, status;

  for (iax = 0; iax < *nwcs; iax++) {
@


0.0.1.5
log
@Checkpoint: column selection (mainly).
@
text
@d31 1
a31 1
    $Id: wcsbth.l,v 0.0.1.4 2007/12/03 06:20:44 cal103 Exp cal103 $
d70 2
a71 2
*   The parser does not check for duplicated keywords, for most keywords it
*   accepts the last encountered.
d75 14
d152 1
a152 3
                           int *colsel, int *keyflag, int *nreject, \
			   /* ::: keyflag */
                           int *nwcs, struct wcsprm **wcs)
d214 3
a216 4
	char *cptr, *errmsg, errtxt[80], exclude[1000], *extkey, *hptr, ptype,
	     stmp[16];
	int  altlin, iax, icol, incl, ipass, ipx, itmp, ix, jx, keytype, nsel,
	     npass, status, valtype, voff;
d248 1
a248 1
	
a258 13
	/* Column selection. */
	nsel = colsel ? colsel[0] : 0;
	incl = (nsel > 0) ? 1 : 0;
	for (icol = 0; icol < 1000; icol++) {
	  exclude[icol] = incl;
	}
	for (icol = 1; icol < nsel; icol++) {
	  if (0 < colsel[icol] && colsel[icol] < 1000) {
	    exclude[colsel[icol]] = !incl;
	  }
	}
	exclude[0] = 0;
	
d296 5
a300 13
	  /* Note that a blank in the sscanf() format string matches zero or
	     more of them in the input. */
	  sscanf(yytext, "WCAX%d%c = %d", &n, &a, &i);
	
	  if (exclude[n]) {
	    /* Obey request to ignore this column. */
	    BEGIN(DISCARD);
	
	  } else {
	    if (ipass == 1) {
	      wcsbth_pass1(BIMGARR, i, 0, n, 0, a, ' ', &alts);
	    }
	    BEGIN(FLUSH);
d302 1
d308 2
a309 3
	  /* Cross-reference supplier. */
	  errmsg = "Cross-references are not currently implemented";
	  BEGIN(ERROR);
d315 2
a316 3
	  /* Cross-reference consumer. */
	  errmsg = "Cross-references are not currently implemented";
	  BEGIN(ERROR);
d391 1
a391 1
	  altlin = 2;
d400 1
a400 1
	  altlin = 2;
d411 1
a411 1
	  altlin = 2;
d1144 2
d1151 1
a1151 1
	    yyless(7);
d1167 2
d1190 1
d1710 2
a1711 13
	  /* Do checks on i, j, m, n, k. */
	  if (exclude[n] || exclude[k]) {
	    /* One or other column is not selected. */
	    if (k && (exclude[n] != exclude[k])) {
	      /* For keywords such as TCn_ka, both columns must be excluded.
	         User error, so return immediately. */
	      yy_delete_buffer(YY_CURRENT_BUFFER);
	      return 3;
	    } else {
	      BEGIN(DISCARD);
	    }
	
	  } else if (i > 99 || j > 99 || m > 99 || n > 999 || k > 999) {
d1715 1
a1715 1
	        sprintf(errmsg, "Axis number exceeds 99");
d1771 1
a1771 1
	
d1800 1
a1800 1
	
d1908 1
a1908 1
	  errmsg = "Malformed keycomment";
a1949 1
          /* Throw away the rest of the line and reset for the next one. */
d2002 1
a2002 1
	
a2003 2
	    yy_delete_buffer(YY_CURRENT_BUFFER);

d2010 3
a2012 1
	    return wcsbth_final(&alts, nwcs, wcs);
d2144 1
a2144 1

@


0.0.1.6
log
@Checkpoint: selection by keyword type; fixed the iCNAM, TCNAM, iCRDE, TCRDE,
iCSYE and TCSYE rules - as usual we have to parse the whole keyword before
declaring it to be non-standard; implemented WCSHDR_ALLIMG in the WCSAXES
rule.
@
text
@d31 1
a31 1
    $Id: wcsbth.l,v 0.0.1.5 2007/12/22 12:59:48 cal103 Exp cal103 $
d138 3
a140 2
                           int keysel, int *colsel, int *nreject, int *nwcs, \
			   struct wcsprm **wcs)
a170 1
  short int pad1;
a176 1
  unsigned char pad2[2];
d204 2
a205 2
	int  altlin, iax, icol, incl, ipass, ipx, itmp, ix, jx, keytype,
	     nsel, npass, status, valtype, voff;
a210 4
	/* The data structures produced. */
	*nwcs = 0;
	*wcs  = 0x0;
	
d248 1
a248 1
	/* Selection by column number. */
d255 2
a256 3
	  itmp = colsel[icol];
	  if (0 < itmp && itmp < 1000) {
	    exclude[itmp] = !incl;
d261 3
a263 11
	/* Selection by keyword type. */
	itmp = keysel;
	keysel = 0;
	if (itmp) {
	  if (itmp & WCSHDR_IMGHEAD) keysel |= IMGHEAD;
	  if (itmp & WCSHDR_BIMGARR) keysel |= BIMGARR;
	  if (itmp & WCSHDR_PIXLIST) keysel |= PIXLIST;
	}
	if (keysel == 0) {
	  keysel = IMGHEAD | BINTAB;
	}
a264 1
	/* Control variables. */
d275 1
d287 4
a290 16
	  keytype = IMGAXIS;
	  if (relax & WCSHDR_ALLIMG) {
	    if (ipass == 1) {
	      sscanf(yytext, "WCSAXES%c= %d", &a, &i);
	      wcsbth_pass1(IMGAXIS, i, 0, 0, 0, a, ' ', &alts);
	    }

	    BEGIN(FLUSH);
	
	  } else if (relax & WCSHDR_reject) {
	    errmsg = "Image-header keyword WCSAXESa in binary table";
	    BEGIN(ERROR);
	
	  } else {
	    /* Pretend we don't recognize it. */
	    BEGIN(DISCARD);
d292 1
a303 1
	    keytype = BIMGARR;
d305 1
a317 1
	  keytype = BIMGARR;
a325 1
	  keytype = BIMGARR;
d638 1
a639 1
	    extkey = "RESTFREQ";
d766 9
a774 3
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    extkey = "iCNAMn";
	    BEGIN(iCCCCn);
d786 9
a794 3
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    extkey = "TCNAMn";
	    BEGIN(TCCCCn);
d816 9
a824 3
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    extkey = "iCRDEn";
	    BEGIN(iCCCCn);
d836 9
a844 3
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    extkey = "TCRDEn";
	    BEGIN(TCCCCn);
d866 9
a874 3
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    extkey = "iCSYEn";
	    BEGIN(iCCCCn);
d886 9
a894 3
	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
	    extkey = "TCSYEn";
	    BEGIN(TCCCCn);
d929 4
d934 1
a934 7
	    keytype = BINTAB;
	    if (relax & WCSHDR_reject) {
	      errmsg = "DOBSna keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d950 4
d955 1
a955 7
	    keytype = IMGAUX;
	    if (relax & WCSHDR_reject) {
	      errmsg = "EPOCH keyword may not have an alternate version code";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1059 4
d1064 1
a1064 7
	    keytype = IMGAUX;
	    if (relax & WCSHDR_reject) {
	      errmsg = "RADECSYS keyword is non-standard";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1145 4
d1150 1
a1150 7
	    keytype = IMGAUX;
	    if (relax & WCSHDR_reject) {
	      errmsg = "VELREF keyword may not have an alternate version code";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1164 4
d1169 1
a1169 7
	    keytype = IMGAUX;
	    if (relax & WCSHDR_reject) {
	      errmsg = "VSOURCEa keyword is deprecated";
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
d1184 4
d1189 2
a1190 8
	    keytype = BINTAB;
	    if (relax & WCSHDR_reject) {
	      errmsg = "VSOUna keyword is deprecated";
	      BEGIN(ERROR);
	    } else {
	      /* Pretend we don't recognize it. */
	      BEGIN(DISCARD);
	    }
a1238 1
	  keytype = IMGAXIS;
d1241 1
a1257 1
	  keytype = IMGAXIS;
d1259 1
a1259 1
	    /* Will also be flagged by <VALUE> as invalid. */
d1275 2
a1276 13
	  if (vptr) {
	    WCSBTH_PUTBACK;
	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
	  } else {
	    keytype = (YY_START == iCCCCn) ? BIMGARR : PIXLIST;
	    if (relax & WCSHDR_reject) {
	      errmsg = errtxt;
	      sprintf(errmsg, "%s keyword is non-standard", extkey);
	      BEGIN(ERROR);
	    } else {
	      BEGIN(DISCARD);
	    }
	  }
d1283 1
a1283 1
	  if (vptr && (relax & WCSHDR_LONGKEY)) {
d1287 6
d1294 2
a1295 15
	    keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
	    if (relax & WCSHDR_reject) {
	      errmsg = errtxt;
	      if (!vptr) {
	        sprintf(errmsg, "%s keyword is non-standard", extkey);
	      } else {
	        sprintf(errmsg,
	          "%s keyword may not have an alternate version code", extkey);
	      }
	      BEGIN(ERROR);
	
	    } else {
	      /* Pretend we don't recognize it. */
	      BEGIN(DISCARD);
	    }
a1352 1
	    keytype = IMGAXIS;
a1609 1
	    keytype = IMGAXIS;
d1717 1
a1717 5
	  if (!(keytype & keysel)) {
	    /* Selection by keyword type. */
	    BEGIN(DISCARD);
	
	  } else if (exclude[n] || exclude[k]) {
a1723 1
	
d1727 1
a1727 1

d1745 1
a1745 1
	  } else if (ipass == 2 && npass == 3 && (keytype & BINTAB)) {
d1749 1
a1749 1
	  } else if (ipass == 3 && (keytype & IMGHEAD)) {
d1967 1
a1967 1
	  /* Throw away the rest of the line and reset for the next one. */
d2023 1
a2023 1
	
d2480 1
a2480 1
    sscanf(yytext, "%d", &velref);
@


0.0.1.7
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.
Final fixes brought to light by testing with tbth1.
@
text
@d31 1
a31 1
    $Id: wcsbth.l,v 0.0.1.6 2007/12/26 04:10:30 cal103 Exp cal103 $
a80 2
%option outfile="wcsbth.c"
%option prefix="wcsbth"
d167 1
a167 1
  int ncol, iax, icol, imgherit;
d171 1
a171 1
  unsigned int *pixlist;
d178 2
a210 1
        int yylex_destroy (void);
d255 1
a255 1
	incl = (nsel > 0);
d259 1
a259 1
	for (icol = 1; icol <= abs(nsel); icol++) {
d302 7
d310 3
a312 3
	  if (!(keytype & keysel)) {
	    /* Ignore this key type. */
	    BEGIN(DISCARD);
d315 2
a316 16
	    if (relax & WCSHDR_ALLIMG) {
	      if (ipass == 1) {
	        sscanf(yytext, "WCSAXES%c= %d", &a, &i);
	        wcsbth_pass1(IMGAXIS, i, 0, 0, 0, a, ' ', &alts);
	      }
	
	      BEGIN(FLUSH);
	
	    } else if (relax & WCSHDR_reject) {
	      errmsg = "Image-header keyword WCSAXESa in binary table";
	      BEGIN(ERROR);
	
	    } else {
	      /* Pretend we don't recognize it. */
	      BEGIN(DISCARD);
	    }
a322 2
	  keytype = BIMGARR;
	
d327 3
a329 2
	  if (!(keytype & keysel) || exclude[n]) {
	    /* Ignore this key type or column. */
d1227 1
a1227 2
	    wcsbth_nkeyrec = 0;
	    errmsg = "Keyrecords following the END keyrecord were ignored";
d1750 1
a1750 1
	      yylex_destroy();
d1860 1
a1860 1
	        /* Is the de-reference necessary? */
d2016 1
a2016 1
	      yylex_destroy();
d2051 1
a2051 1
	    yylex_destroy();
@
