mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Rearrange order of operations in heap_create_with_catalog so that if
two transactions create the same table name concurrently, the one that fails will complain about unique index pg_class_relname_index, rather than about pg_type_typname_index which'll confuse most people. Free side benefit: pg_class.reltype is correctly linked to the pg_type entry now. It's been zero in all but the preloaded pg_class entries since who knows when.
This commit is contained in:
		
							parent
							
								
									d8c4cb740c
								
							
						
					
					
						commit
						aa88e59ade
					
				| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.158 2001/01/24 19:42:51 momjian Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.159 2001/02/12 20:07:21 tgl Exp $ | ||||
|  * | ||||
|  * | ||||
|  * INTERFACE ROUTINES | ||||
| @ -68,15 +68,15 @@ | ||||
| 
 | ||||
| 
 | ||||
| static void AddNewRelationTuple(Relation pg_class_desc, | ||||
| 					Relation new_rel_desc, Oid new_rel_oid, | ||||
| 					int natts, | ||||
| 					char relkind, char *temp_relname); | ||||
| 					Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, | ||||
| 					int natts, char relkind, char *temp_relname); | ||||
| static void DeleteAttributeTuples(Relation rel); | ||||
| static void DeleteRelationTuple(Relation rel); | ||||
| static void DeleteTypeTuple(Relation rel); | ||||
| static void RelationRemoveIndexes(Relation relation); | ||||
| static void RelationRemoveInheritance(Relation relation); | ||||
| static void AddNewRelationType(char *typeName, Oid new_rel_oid); | ||||
| static void AddNewRelationType(char *typeName, Oid new_rel_oid, | ||||
| 							   Oid new_type_oid); | ||||
| static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin, | ||||
| 				 bool updatePgAttribute); | ||||
| static void StoreRelCheck(Relation rel, char *ccname, char *ccbin); | ||||
| @ -317,6 +317,7 @@ heap_create(char *relname, | ||||
| 	strcpy(RelationGetPhysicalRelationName(rel), relname); | ||||
| 	rel->rd_rel->relkind = RELKIND_UNCATALOGED; | ||||
| 	rel->rd_rel->relnatts = natts; | ||||
| 	rel->rd_rel->reltype = InvalidOid; | ||||
| 	if (tupDesc->constr) | ||||
| 		rel->rd_rel->relchecks = tupDesc->constr->num_check; | ||||
| 
 | ||||
| @ -325,12 +326,6 @@ heap_create(char *relname, | ||||
| 
 | ||||
| 	RelationGetRelid(rel) = relid; | ||||
| 
 | ||||
| 	if (nailme) | ||||
| 	{ | ||||
| 		/* for system relations, set the reltype field here */ | ||||
| 		rel->rd_rel->reltype = relid; | ||||
| 	} | ||||
| 
 | ||||
| 	rel->rd_node.tblNode = tblNode; | ||||
| 	rel->rd_node.relNode = relid; | ||||
| 	rel->rd_rel->relfilenode = relid; | ||||
| @ -373,18 +368,17 @@ heap_storage_create(Relation rel) | ||||
|  *		   performs a scan to ensure that no relation with the | ||||
|  *		   same name already exists. | ||||
|  * | ||||
|  *		3) heap_create_with_catalog() is called to create the new relation | ||||
|  *		   on disk. | ||||
|  *		3) heap_create() is called to create the new relation on disk. | ||||
|  * | ||||
|  *		4) TypeDefine() is called to define a new type corresponding | ||||
|  *		4) AddNewRelationTuple() is called to register the | ||||
|  *		   relation in pg_class. | ||||
|  * | ||||
|  *		5) TypeCreate() is called to define a new type corresponding | ||||
|  *		   to the new relation. | ||||
|  * | ||||
|  *		5) AddNewAttributeTuples() is called to register the | ||||
|  *		6) AddNewAttributeTuples() is called to register the | ||||
|  *		   new relation's schema in pg_attribute. | ||||
|  * | ||||
|  *		6) AddNewRelationTuple() is called to register the | ||||
|  *		   relation itself in the catalogs. | ||||
|  * | ||||
|  *		7) StoreConstraints is called ()		- vadim 08/22/97 | ||||
|  * | ||||
|  *		8) the relations are closed and the new relation's oid | ||||
| @ -656,6 +650,7 @@ static void | ||||
| AddNewRelationTuple(Relation pg_class_desc, | ||||
| 					Relation new_rel_desc, | ||||
| 					Oid new_rel_oid, | ||||
| 					Oid new_type_oid, | ||||
| 					int natts, | ||||
| 					char relkind, | ||||
| 					char *temp_relname) | ||||
| @ -665,7 +660,7 @@ AddNewRelationTuple(Relation pg_class_desc, | ||||
| 	Relation	idescs[Num_pg_class_indices]; | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	first we munge some of the information in our | ||||
| 	 *	first we update some of the information in our | ||||
| 	 *	uncataloged relation's relation descriptor. | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| @ -694,6 +689,7 @@ AddNewRelationTuple(Relation pg_class_desc, | ||||
| 	new_rel_reltup->reltuples = 1000; | ||||
| 
 | ||||
| 	new_rel_reltup->relowner = GetUserId(); | ||||
| 	new_rel_reltup->reltype = new_type_oid; | ||||
| 	new_rel_reltup->relkind = relkind; | ||||
| 	new_rel_reltup->relnatts = natts; | ||||
| 
 | ||||
| @ -705,6 +701,8 @@ AddNewRelationTuple(Relation pg_class_desc, | ||||
| 	tup = heap_addheader(Natts_pg_class_fixed, | ||||
| 						 CLASS_TUPLE_SIZE, | ||||
| 						 (char *) new_rel_reltup); | ||||
| 
 | ||||
| 	/* force tuple to have the desired OID */ | ||||
| 	tup->t_data->t_oid = new_rel_oid; | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -738,10 +736,8 @@ AddNewRelationTuple(Relation pg_class_desc, | ||||
|  * -------------------------------- | ||||
|  */ | ||||
| static void | ||||
| AddNewRelationType(char *typeName, Oid new_rel_oid) | ||||
| AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid) | ||||
| { | ||||
| 	Oid			new_type_oid; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The sizes are set to oid size because it makes implementing sets | ||||
| 	 * MUCH easier, and no one (we hope) uses these fields to figure out | ||||
| @ -750,23 +746,25 @@ AddNewRelationType(char *typeName, Oid new_rel_oid) | ||||
| 	 * actually get is the oid of a tuple in the pg_proc catalog, so the | ||||
| 	 * size of the "set" is the size of an oid. Similarly, byval being | ||||
| 	 * true makes sets much easier, and it isn't used by anything else. | ||||
| 	 * Note the assumption that OIDs are the same size as int4s. | ||||
| 	 * | ||||
| 	 * XXX Note the assumption that OIDs are the same size as int4s. | ||||
| 	 */ | ||||
| 	new_type_oid = TypeCreate(typeName, /* type name */ | ||||
| 							  new_rel_oid,		/* relation oid */ | ||||
| 							  sizeof(Oid),		/* internal size */ | ||||
| 							  sizeof(Oid),		/* external size */ | ||||
| 							  'c',		/* type-type (catalog) */ | ||||
| 							  ',',		/* default array delimiter */ | ||||
| 							  "int4in", /* input procedure */ | ||||
| 							  "int4out",		/* output procedure */ | ||||
| 							  "int4in", /* receive procedure */ | ||||
| 							  "int4out",		/* send procedure */ | ||||
| 							  NULL,		/* array element type - irrelevent */ | ||||
| 							  "-",		/* default type value */ | ||||
| 							  (bool) 1, /* passed by value */ | ||||
| 							  'i',		/* default alignment */ | ||||
| 							  'p');		/* Not TOASTable */ | ||||
| 	TypeCreate(typeName,		/* type name */ | ||||
| 			   new_type_oid,	/* preassigned oid for type */ | ||||
| 			   new_rel_oid,		/* relation oid */ | ||||
| 			   sizeof(Oid),		/* internal size */ | ||||
| 			   sizeof(Oid),		/* external size */ | ||||
| 			   'c',				/* type-type (catalog) */ | ||||
| 			   ',',				/* default array delimiter */ | ||||
| 			   "int4in",		/* input procedure */ | ||||
| 			   "int4out",		/* output procedure */ | ||||
| 			   "int4in",		/* receive procedure */ | ||||
| 			   "int4out",		/* send procedure */ | ||||
| 			   NULL,			/* array element type - irrelevant */ | ||||
| 			   "-",				/* default type value */ | ||||
| 			   true,			/* passed by value */ | ||||
| 			   'i',				/* default alignment */ | ||||
| 			   'p');			/* Not TOASTable */ | ||||
| } | ||||
| 
 | ||||
| /* --------------------------------
 | ||||
| @ -785,6 +783,7 @@ heap_create_with_catalog(char *relname, | ||||
| 	Relation	pg_class_desc; | ||||
| 	Relation	new_rel_desc; | ||||
| 	Oid			new_rel_oid; | ||||
| 	Oid			new_type_oid; | ||||
| 	int			natts = tupdesc->natts; | ||||
| 	char	   *temp_relname = NULL; | ||||
| 
 | ||||
| @ -814,18 +813,10 @@ heap_create_with_catalog(char *relname, | ||||
| 	} | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	RelnameFindRelid couldn't detect simultaneous | ||||
| 	 *	creation. Uniqueness will be really checked by unique | ||||
| 	 *	indexes of system tables but we couldn't check it here. | ||||
| 	 *	We have to postpone creating the disk file for this | ||||
| 	 *	relation. | ||||
| 	 *	Another boolean parameter "storage_create" was added | ||||
| 	 *	to heap_create() function. If the parameter is false | ||||
| 	 *	heap_create() only registers an uncataloged relation | ||||
| 	 *	to relation cache and heap_storage_create() should be | ||||
| 	 *	called later. | ||||
| 	 *	We could pull its relation oid from the newly formed | ||||
| 	 *	relation descriptor. | ||||
| 	 *	Tell heap_create not to create a physical file; we'll do that | ||||
| 	 *	below after all our catalog updates are done.  (This isn't really | ||||
| 	 *	necessary anymore, but we may as well avoid the cycles of creating | ||||
| 	 *	and deleting the file in case we fail.) | ||||
| 	 * | ||||
| 	 *	Note: The call to heap_create() changes relname for | ||||
| 	 *	temp tables; it becomes the true physical relname. | ||||
| @ -836,24 +827,18 @@ heap_create_with_catalog(char *relname, | ||||
| 	new_rel_desc = heap_create(relname, tupdesc, istemp, false, | ||||
| 							   allow_system_table_mods); | ||||
| 
 | ||||
| 	/* Fetch the relation OID assigned by heap_create */ | ||||
| 	new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid; | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	since defining a relation also defines a complex type, | ||||
| 	 *	we add a new system type corresponding to the new relation. | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	AddNewRelationType(relname, new_rel_oid); | ||||
| 	/* Assign an OID for the relation's tuple type */ | ||||
| 	new_type_oid = newoid(); | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	now add tuples to pg_attribute for the attributes in | ||||
| 	 *	our new relation. | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	AddNewAttributeTuples(new_rel_oid, tupdesc); | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	now update the information in pg_class. | ||||
| 	 *	now create an entry in pg_class for the relation. | ||||
| 	 * | ||||
| 	 *	NOTE: we could get a unique-index failure here, in case someone else | ||||
| 	 *	is creating the same relation name in parallel but hadn't committed | ||||
| 	 *	yet when we checked for a duplicate name above. | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock); | ||||
| @ -861,10 +846,28 @@ heap_create_with_catalog(char *relname, | ||||
| 	AddNewRelationTuple(pg_class_desc, | ||||
| 						new_rel_desc, | ||||
| 						new_rel_oid, | ||||
| 						new_type_oid, | ||||
| 						natts, | ||||
| 						relkind, | ||||
| 						temp_relname); | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	since defining a relation also defines a complex type, | ||||
| 	 *	we add a new system type corresponding to the new relation. | ||||
| 	 * | ||||
| 	 *	NOTE: we could get a unique-index failure here, in case the same name | ||||
| 	 *	has already been used for a type. | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	AddNewRelationType(relname, new_rel_oid, new_type_oid); | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	now add tuples to pg_attribute for the attributes in | ||||
| 	 *	our new relation. | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	AddNewAttributeTuples(new_rel_oid, tupdesc); | ||||
| 
 | ||||
| 	StoreConstraints(new_rel_desc); | ||||
| 
 | ||||
| 	if (istemp) | ||||
| @ -912,7 +915,6 @@ heap_create_with_catalog(char *relname, | ||||
|  *		attribute catalog (needed?).  (Anything else?) | ||||
|  * | ||||
|  *		get proper relation from relation catalog (if not arg) | ||||
|  *		check if relation is vital (strcmp()/reltype?) | ||||
|  *		scan attribute catalog deleting attributes of reldesc | ||||
|  *				(necessary?) | ||||
|  *		delete relation from relation catalog | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.58 2001/01/24 19:42:52 momjian Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.59 2001/02/12 20:07:21 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -46,18 +46,17 @@ TypeGetWithOpenRelation(Relation pg_type_desc, | ||||
| 	HeapScanDesc scan; | ||||
| 	HeapTuple	tup; | ||||
| 	Oid			typoid; | ||||
| 
 | ||||
| 	static ScanKeyData typeKey[1] = { | ||||
| 		{0, Anum_pg_type_typname, F_NAMEEQ} | ||||
| 	}; | ||||
| 	ScanKeyData typeKey[1]; | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	initialize the scan key and begin a scan of pg_type | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	fmgr_info(F_NAMEEQ, &typeKey[0].sk_func); | ||||
| 	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs; | ||||
| 	typeKey[0].sk_argument = PointerGetDatum(typeName); | ||||
| 	ScanKeyEntryInitialize(typeKey, | ||||
| 						   0, | ||||
| 						   Anum_pg_type_typname, | ||||
| 						   F_NAMEEQ, | ||||
| 						   PointerGetDatum(typeName)); | ||||
| 
 | ||||
| 	scan = heap_beginscan(pg_type_desc, | ||||
| 						  0, | ||||
| @ -269,10 +268,16 @@ TypeShellMake(char *typeName) | ||||
|  *		TypeCreate | ||||
|  * | ||||
|  *		This does all the necessary work needed to define a new type. | ||||
|  * | ||||
|  * NOTE: if assignedTypeOid is not InvalidOid, then that OID is assigned to | ||||
|  * the new type (which, therefore, cannot already exist as a shell type). | ||||
|  * This hack is only intended for use in creating a relation's associated | ||||
|  * type, where we need to have created the relation tuple already. | ||||
|  * ---------------------------------------------------------------- | ||||
|  */ | ||||
| Oid | ||||
| TypeCreate(char *typeName, | ||||
| 		   Oid assignedTypeOid, | ||||
| 		   Oid relationOid,		/* only for 'c'atalog typeTypes */ | ||||
| 		   int16 internalSize, | ||||
| 		   int16 externalSize, | ||||
| @ -292,35 +297,28 @@ TypeCreate(char *typeName, | ||||
| 				j; | ||||
| 	Relation	pg_type_desc; | ||||
| 	HeapScanDesc pg_type_scan; | ||||
| 
 | ||||
| 	Oid			typeObjectId; | ||||
| 	Oid			elementObjectId = InvalidOid; | ||||
| 
 | ||||
| 	HeapTuple	tup; | ||||
| 	char		nulls[Natts_pg_type]; | ||||
| 	char		replaces[Natts_pg_type]; | ||||
| 	Datum		values[Natts_pg_type]; | ||||
| 
 | ||||
| 	char	   *procname; | ||||
| 	char	   *procs[4]; | ||||
| 	bool		defined; | ||||
| 	NameData	name; | ||||
| 	TupleDesc	tupDesc; | ||||
| 	Oid			argList[FUNC_MAX_ARGS]; | ||||
| 
 | ||||
| 	static ScanKeyData typeKey[1] = { | ||||
| 		{0, Anum_pg_type_typname, F_NAMEEQ} | ||||
| 	}; | ||||
| 
 | ||||
| 	fmgr_info(F_NAMEEQ, &typeKey[0].sk_func); | ||||
| 	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs; | ||||
| 	ScanKeyData typeKey[1]; | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	check that the type is not already defined. | ||||
| 	 *	check that the type is not already defined.  It might exist as | ||||
| 	 *	a shell type, however (but only if assignedTypeOid is not given). | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	typeObjectId = TypeGet(typeName, &defined); | ||||
| 	if (OidIsValid(typeObjectId) && defined) | ||||
| 	if (OidIsValid(typeObjectId) && | ||||
| 		(defined || assignedTypeOid != InvalidOid)) | ||||
| 		elog(ERROR, "TypeCreate: type %s already defined", typeName); | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| @ -468,7 +466,12 @@ TypeCreate(char *typeName, | ||||
| 	 */ | ||||
| 	pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); | ||||
| 
 | ||||
| 	typeKey[0].sk_argument = PointerGetDatum(typeName); | ||||
| 	ScanKeyEntryInitialize(typeKey, | ||||
| 						   0, | ||||
| 						   Anum_pg_type_typname, | ||||
| 						   F_NAMEEQ, | ||||
| 						   PointerGetDatum(typeName)); | ||||
| 
 | ||||
| 	pg_type_scan = heap_beginscan(pg_type_desc, | ||||
| 								  0, | ||||
| 								  SnapshotSelf, /* cache? */ | ||||
| @ -484,6 +487,10 @@ TypeCreate(char *typeName, | ||||
| 	tup = heap_getnext(pg_type_scan, 0); | ||||
| 	if (HeapTupleIsValid(tup)) | ||||
| 	{ | ||||
| 		/* should not happen given prior test? */ | ||||
| 		if (assignedTypeOid != InvalidOid) | ||||
| 			elog(ERROR, "TypeCreate: type %s already defined", typeName); | ||||
| 
 | ||||
| 		tup = heap_modifytuple(tup, | ||||
| 							   pg_type_desc, | ||||
| 							   values, | ||||
| @ -502,6 +509,9 @@ TypeCreate(char *typeName, | ||||
| 							 values, | ||||
| 							 nulls); | ||||
| 
 | ||||
| 		/* preassign tuple Oid, if one was given */ | ||||
| 		tup->t_data->t_oid = assignedTypeOid; | ||||
| 
 | ||||
| 		heap_insert(pg_type_desc, tup); | ||||
| 
 | ||||
| 		typeObjectId = tup->t_data->t_oid; | ||||
|  | ||||
| @ -10,7 +10,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.51 2001/01/24 19:42:52 momjian Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.52 2001/02/12 20:07:21 tgl Exp $ | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *	  The "DefineFoo" routines take the parse tree and pick out the | ||||
| @ -640,6 +640,7 @@ DefineType(char *typeName, List *parameters) | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	TypeCreate(typeName,		/* type name */ | ||||
| 			   InvalidOid,		/* preassigned type oid (not done here) */ | ||||
| 			   InvalidOid,		/* relation oid (n/a here) */ | ||||
| 			   internalLength,	/* internal size */ | ||||
| 			   externalLength,	/* external size */ | ||||
| @ -652,7 +653,7 @@ DefineType(char *typeName, List *parameters) | ||||
| 			   elemName,		/* element type name */ | ||||
| 			   defaultValue,	/* default type value */ | ||||
| 			   byValue,			/* passed by value */ | ||||
| 			   alignment, | ||||
| 			   alignment,		/* required alignment */ | ||||
| 			   storage);		/* TOAST strategy */ | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| @ -663,6 +664,7 @@ DefineType(char *typeName, List *parameters) | ||||
| 	shadow_type = makeArrayTypeName(typeName); | ||||
| 
 | ||||
| 	TypeCreate(shadow_type,		/* type name */ | ||||
| 			   InvalidOid,		/* preassigned type oid (not done here) */ | ||||
| 			   InvalidOid,		/* relation oid (n/a here) */ | ||||
| 			   -1,				/* internal size */ | ||||
| 			   -1,				/* external size */ | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: pg_type.h,v 1.100 2001/01/24 19:43:22 momjian Exp $ | ||||
|  * $Id: pg_type.h,v 1.101 2001/02/12 20:07:20 tgl Exp $ | ||||
|  * | ||||
|  * NOTES | ||||
|  *	  the genbki.sh script reads this file and generates .bki | ||||
| @ -420,6 +420,7 @@ DESCR("numeric(precision, decimal), arbitrary precision number"); | ||||
| extern Oid	TypeGet(char *typeName, bool *defined); | ||||
| extern Oid	TypeShellMake(char *typeName); | ||||
| extern Oid TypeCreate(char *typeName, | ||||
| 		   Oid assignedTypeOid, | ||||
| 		   Oid relationOid, | ||||
| 		   int16 internalSize, | ||||
| 		   int16 externalSize, | ||||
| @ -431,7 +432,8 @@ extern Oid TypeCreate(char *typeName, | ||||
| 		   char *sendProcedure, | ||||
| 		   char *elementTypeName, | ||||
| 		   char *defaultTypeValue, | ||||
| 		   bool passedByValue, char alignment, | ||||
| 		   bool passedByValue, | ||||
| 		   char alignment, | ||||
| 		   char storage); | ||||
| extern void TypeRename(const char *oldTypeName, const char *newTypeName); | ||||
| extern char *makeArrayTypeName(char *typeName); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user