private void doWrite(DataType dt, TaskMonitor monitor, boolean throwExceptionOnInvalidType)
			throws IOException, CancelledException {
		if (dt == null) {
			return;
		}
		if (dt instanceof FunctionDefinition) {
			return;
		}
		if (dt instanceof FactoryDataType) {
			IllegalArgumentException iae =
				new IllegalArgumentException("Factory data types may not be written");
			if (throwExceptionOnInvalidType) {
				throw iae;
			}
			Msg.error(this, "Factory data types may not be written - type: " + dt);
		}
		if (dt instanceof Pointer || dt instanceof Array || dt instanceof BitFieldDataType) {
			write(getBaseDataType(dt), monitor);
			return;
		}

		dt = dt.clone(dtm); // force resize/repack for target data organization

		if (resolved.contains(dt)) {
			return;
		}

		resolved.add(dt);

		DataType resolvedType = resolvedTypeMap.get(dt.getName());
		if (resolvedType != null) {
			if (resolvedType.isEquivalent(dt)) {
				return; // skip equivalent type with same name as a resolved type
			}
			if (dt instanceof TypeDef) {
				DataType baseType = ((TypeDef) dt).getBaseDataType();
				if (resolvedType instanceof Composite || resolvedType instanceof Enum) {
					if (baseType.isEquivalent(resolvedType)) {
						// auto-typedef already generated for Composite or Enum
						return;
					}
				}
			}
			writer.write(EOL);
			writer.write(comment("WARNING! conflicting data type names: " + dt.getPathName() +
				" - " + resolvedType.getPathName()));
			writer.write(EOL);
			writer.write(EOL);
			return;
		}

		resolvedTypeMap.put(dt.getName(), dt);

		++writerDepth;

		if (dt.equals(DataType.DEFAULT)) {
			writer.write("typedef unsigned char   " + DataType.DEFAULT.getName() + ";");
			writer.write(EOL);
			writer.write(EOL);
		}
		else if (dt instanceof Dynamic) {
			writeDynamicBuiltIn((Dynamic) dt, monitor);
		}
		else if (dt instanceof Structure) {
			Structure struct = (Structure) dt;
			writeCompositePreDeclaration(struct, monitor);
			deferredCompositeDeclarations.add(struct);
		}
		else if (dt instanceof Union) {
			Union union = (Union) dt;
			writeCompositePreDeclaration(union, monitor);
			deferredCompositeDeclarations.add(union);
		}
		else if (dt instanceof Enum) {
			writeEnum((Enum) dt, monitor);
		}
		else if (dt instanceof TypeDef) {
			writeTypeDef((TypeDef) dt, monitor);
		}
		else if (dt instanceof BuiltInDataType) {
			writeBuiltIn((BuiltInDataType) dt, monitor);
		}
		else if (dt instanceof BitFieldDataType) {
			// skip
		}
		else {
			writer.write(EOL);
			writer.write(EOL);
			writer.write(comment("Unable to write datatype. Type unrecognized: " + dt.getClass()));
			writer.write(EOL);
			writer.write(EOL);
		}

		if (writerDepth == 1) {
			writeDeferredDeclarations(monitor);
		}
		--writerDepth;
	}
Writes the data type as ANSI-C using the underlying writer.
@param dt the data type to write as ANSI-C
@param monitor the task monitor
@throws IOException if there is an exception writing the output
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeWriter.java