// Path: source/transpiler/com/stormmq/java2c/transpiler/conversion/c/VariableDeclaration.java
// public final class VariableDeclaration implements Writable
// {
// 	@NotNull private final StorageClass storageClass;
// 	private final boolean isConst;
// 	private final boolean isVolatile;
// 	@NotNull private final String cTypeName;
// 	@NotNull private final String name;
// 	@NotNull private final GccAttributes<GccVariableAttributeName> gccAttributes;
// 
// 	// The cTypeName needs to include any 'pointer' attributes, eg restrict, volatile, const, *
// 	public VariableDeclaration(@NotNull final StorageClass storageClass, final boolean isConst, final boolean isVolatile, @NotNull final String cTypeName, @NotNull final String name, @NotNull final GccAttributes<GccVariableAttributeName> gccAttributes)
// 	{
// 		this.storageClass = storageClass;
// 		this.isConst = isConst;
// 		this.isVolatile = isVolatile;
// 		this.cTypeName = cTypeName;
// 		this.name = name;
// 		this.gccAttributes = gccAttributes;
// 	}
// 
// 	public void write(@NotNull final Writer writer) throws IOException
// 	{
// 		if (storageClass != auto)
// 		{
// 			writer.write(storageClass.storageClass);
// 			writer.write(' ');
// 		}
// 
// 		if (isConst)
// 		{
// 			writer.write("const ");
// 		}
// 
// 		if (isVolatile)
// 		{
// 			writer.write("volatile ");
// 		}
// 
// 		writer.write(cTypeName);
// 		writer.write(' ');
// 		writer.write(name);
// 
// 		gccAttributes.write(writer);
// 
// 		writer.write(';');
// 	}
// }
// 
// Path: source/transpiler/com/stormmq/java2c/transpiler/CharsetHelper.java
// @NotNull public static final Charset Utf8 = forName("UTF-8");


import com.stormmq.java2c.transpiler.conversion.c.VariableDeclaration;
import org.jetbrains.annotations.NotNull;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.QualifiedNameable;
import java.io.*;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import static com.stormmq.java2c.transpiler.CharsetHelper.Utf8;
import static java.lang.String.format;
import static java.util.Locale.ENGLISH;
import static java.util.regex.Pattern.compile;
import static javax.lang.model.element.Modifier.STRICTFP;
package com.stormmq.java2c.transpiler.conversion;




public class CMaker
{
	@NotNull private static final Pattern DotMatch = compile("\\.");
	@NotNull private final CFileCreator cFileCreator;

	public CMaker(@NotNull final CFileCreator cFileCreator)
	{
		this.cFileCreator = cFileCreator;
	}

	public void makeFiles(@NotNull final QualifiedNameable qualifiedNameable, final boolean isPackage, @NotNull final List<String> libraryIncludes, @NotNull final List<String> localIncludes, @NotNull final List<VariableDeclaration> publicConstants) throws IOException
	{
		final Set<Modifier> modifiers = qualifiedNameable.getModifiers();

		// strictfp in essence requires that we use float and double
		// w/o strictfp, we could use float_t and double_t, which are normally 80-bit long double
		// in practice, this is going to confuse the hell out of users
		if (modifiers.contains(STRICTFP))
		{
			/*
			The effect of the strictfp modifier is to make all float or double expressions within the class declaration (including within variable initializers,
			instance initializers, static initializers, and constructors) be explicitly FP-strict (§15.4).
			This implies that all methods declared in the class, and all nested types declared in the class, are implicitly strictfp.

				In other words, use double_t / float_t types from math.h for local variables, if NOT using strictfp
				Generate a cast from double_t to double and float_t to float; need to check that the thing we're casting is, of course, actually a local variable of the relevant type... and cast order precedence is maintained (if the user then casts to something else
			 */

			/*
				On an interface, makes all implementations of all methods strict...
			 */
		}



		final String qualifiedName = qualifiedNameable.getQualifiedName().toString();
		// Includes to other modules will need to use a relative path syntax...

		final File headerFile = cFileCreator.headerFilePath(qualifiedName, isPackage);
		try(final OutputStream outputStream = new FileOutputStream(headerFile, true))
		{
// Path: source/transpiler/com/stormmq/java2c/transpiler/conversion/c/VariableDeclaration.java
// public final class VariableDeclaration implements Writable
// {
// 	@NotNull private final StorageClass storageClass;
// 	private final boolean isConst;
// 	private final boolean isVolatile;
// 	@NotNull private final String cTypeName;
// 	@NotNull private final String name;
// 	@NotNull private final GccAttributes<GccVariableAttributeName> gccAttributes;
// 
// 	// The cTypeName needs to include any 'pointer' attributes, eg restrict, volatile, const, *
// 	public VariableDeclaration(@NotNull final StorageClass storageClass, final boolean isConst, final boolean isVolatile, @NotNull final String cTypeName, @NotNull final String name, @NotNull final GccAttributes<GccVariableAttributeName> gccAttributes)
// 	{
// 		this.storageClass = storageClass;
// 		this.isConst = isConst;
// 		this.isVolatile = isVolatile;
// 		this.cTypeName = cTypeName;
// 		this.name = name;
// 		this.gccAttributes = gccAttributes;
// 	}
// 
// 	public void write(@NotNull final Writer writer) throws IOException
// 	{
// 		if (storageClass != auto)
// 		{
// 			writer.write(storageClass.storageClass);
// 			writer.write(' ');
// 		}
// 
// 		if (isConst)
// 		{
// 			writer.write("const ");
// 		}
// 
// 		if (isVolatile)
// 		{
// 			writer.write("volatile ");
// 		}
// 
// 		writer.write(cTypeName);
// 		writer.write(' ');
// 		writer.write(name);
// 
// 		gccAttributes.write(writer);
// 
// 		writer.write(';');
// 	}
// }
// 
// Path: source/transpiler/com/stormmq/java2c/transpiler/CharsetHelper.java
// @NotNull public static final Charset Utf8 = forName("UTF-8");


// Path: source/transpiler/com/stormmq/java2c/transpiler/conversion/CMaker.java
import com.stormmq.java2c.transpiler.conversion.c.VariableDeclaration;
import org.jetbrains.annotations.NotNull;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.QualifiedNameable;
import java.io.*;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import static com.stormmq.java2c.transpiler.CharsetHelper.Utf8;
import static java.lang.String.format;
import static java.util.Locale.ENGLISH;
import static java.util.regex.Pattern.compile;
import static javax.lang.model.element.Modifier.STRICTFP;

package com.stormmq.java2c.transpiler.conversion;




public class CMaker
{
	@NotNull private static final Pattern DotMatch = compile("\\.");
	@NotNull private final CFileCreator cFileCreator;

	public CMaker(@NotNull final CFileCreator cFileCreator)
	{
		this.cFileCreator = cFileCreator;
	}

	public void makeFiles(@NotNull final QualifiedNameable qualifiedNameable, final boolean isPackage, @NotNull final List<String> libraryIncludes, @NotNull final List<String> localIncludes, @NotNull final List<VariableDeclaration> publicConstants) throws IOException
	{
		final Set<Modifier> modifiers = qualifiedNameable.getModifiers();

		// strictfp in essence requires that we use float and double
		// w/o strictfp, we could use float_t and double_t, which are normally 80-bit long double
		// in practice, this is going to confuse the hell out of users
		if (modifiers.contains(STRICTFP))
		{
			/*
			The effect of the strictfp modifier is to make all float or double expressions within the class declaration (including within variable initializers,
			instance initializers, static initializers, and constructors) be explicitly FP-strict (§15.4).
			This implies that all methods declared in the class, and all nested types declared in the class, are implicitly strictfp.

				In other words, use double_t / float_t types from math.h for local variables, if NOT using strictfp
				Generate a cast from double_t to double and float_t to float; need to check that the thing we're casting is, of course, actually a local variable of the relevant type... and cast order precedence is maintained (if the user then casts to something else
			 */

			/*
				On an interface, makes all implementations of all methods strict...
			 */
		}



		final String qualifiedName = qualifiedNameable.getQualifiedName().toString();
		// Includes to other modules will need to use a relative path syntax...

		final File headerFile = cFileCreator.headerFilePath(qualifiedName, isPackage);
		try(final OutputStream outputStream = new FileOutputStream(headerFile, true))
		{
			try (final Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream, Utf8), 4096))