1 /*
2  * dcc.c -- An hcode compiler/decompiler for Hexen II by Eric Hobbs
3  * $Id: dcc.c 5787 2017-01-03 22:22:34Z sezero $
4  *
5  * Copyright (C) 1996-1997 Id Software, Inc.
6  * Copyright (C) 1997 Eric Hobbs <elhobbs@comcast.net>
7  * Copyright (C) 2005-2012 O.Sezer <sezero@users.sourceforge.net>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or (at
12  * your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * See the GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  */
24 
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include "q_stdinc.h"
29 #include "compiler.h"
30 #include "arch_def.h"
31 #include "cmdlib.h"
32 #include "util_io.h"
33 #include "qcc.h"
34 #include "dcc.h"
35 #include "q_endian.h"
36 
37 // MACROS ------------------------------------------------------------------
38 
39 #define	MAX_DEC_FILES	512
40 
41 // TYPES -------------------------------------------------------------------
42 
43 struct flowinfo_t
44 {
45 	int	if_cnt;
46 	int	do_cnt;
47 };
48 
49 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
50 
51 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
52 
53 /* IMPORTANT NOTE about functions taking a gofs_t argument:  If you pass a
54  * dstatement_t->a, b or c (signed short) value to them and the function
55  * compares that value to a ddef_t->ofs value (unsigned short), then you
56  * must explicitly cast that dstatement_t->a, b or c to unsigned short.
57  * BackBuildReturnType() is an exception, because it compares its gofs_t
58  * argument to dstatement_t->a, b or c values, therefore you must not do
59  * that casting for that case.
60  */
61 static void	Make_Immediate (gofs_t ofs, const char *s);
62 static char	*Get_Immediate (gofs_t ofs);
63 static void	Clear_Immediates (void);
64 static void	PR_Indent (void);
65 static void	PR_FunctionHeader (dfunction_t *df);
66 static void	PR_Print (const char *s,...) FUNC_PRINTF(1,2);
67 static const char *PR_PrintGlobal (gofs_t ofs, def_t* typ);
68 static ddef_t	*PR_GetField (const char *name, ddef_t*);
69 static int	DEC_GetFunctionIdxByName (const char *name);
70 static void	PR_LocalGlobals (void);
71 static int	DEC_AlreadySeen (const char *fname);
72 static ddef_t	*DEC_GetParameter (gofs_t ofs);
73 static const char *GetFieldFunctionHeader (const char *s_name);
74 static void	DccStatement (dstatement_t *s);
75 static void	AddProgramFlowInfo (dfunction_t *df);
76 static void	PR_Locals (dfunction_t *df);
77 static const char * PR_ValueString (etype_t type, void *val);
78 static const char *DCC_ValueString (etype_t type, void *val);
79 		/* same as PR_ValueString(), differing
80 		 * in float/vector print precision.  */
81 static unsigned short	GetReturnType (int func);
82 static unsigned short	BackBuildReturnType (dfunction_t *df, dstatement_t *dsf, gofs_t ofs);
83 static unsigned short	GetType (gofs_t ofs);
84 static unsigned short	GetLastFunctionReturn (dfunction_t *df, dstatement_t *ds);
85 
86 static void	Init_Dcc (void);
87 static void	DEC_ReadData (const char *srcfile);
88 static void	Dcc_Functions (void);
89 static void	FindBuiltinParameters (int func);
90 static void	DccFunctionOP (unsigned short op);
91 static void	PR_PrintFunction (const char *name);
92 static def_t	*PR_DefForFieldOfs (gofs_t ofs);
93 static const char *PR_String (const char *string);
94 
95 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
96 
97 // PUBLIC DATA DEFINITIONS -------------------------------------------------
98 
99 // PRIVATE DATA DEFINITIONS ------------------------------------------------
100 
101 static const char *type_names[8] =
102 {
103 	"void",
104 	"string",
105 	"float",
106 	"vector",
107 	"entity",
108 	"ev_field",
109 	"void()",
110 	"ev_pointer"
111 };
112 
113 static dprograms_t	*progs;
114 static dfunction_t	*pr_functions;
115 static ddef_t		*pr_globaldefs;
116 static ddef_t		*pr_fielddefs;
117 static dstatement_t	*pr_statements;
118 static char		*pr_strings;
119 static int		progs_length;
120 
121 static dfunction_t	*cfunc;
122 static struct flowinfo_t	*flowinfo;
123 
124 static qboolean		FILE_NUM_FOR_NAME;
125 static qboolean		pr_dumpasm;
126 static qboolean		printassign;
127 static int		pr_infoonly;
128 
129 static FILE	*PR_FILE;
130 static char	**func_headers;
131 static char	**temp_val;
132 
133 static int	lindent;
134 static char	**DEC_FilesSeen;
135 static int	DEC_FileCtr;
136 
137 /* avoid infinite recursion in GetFieldFunctionHeader() which has
138  * thankfully only one caller, PR_LocalGlobals(). this solution
139  * is naive, cheesy, [insert more here.. or find a better one...] */
140 #define GFFH_MAX_DEPTH	64
141 static int	GFFH_depth = 0;
142 
143 // CODE --------------------------------------------------------------------
144 
PR_PrintStringAtOfs(gofs_t ofs,def_t * typ)145 static const char *PR_PrintStringAtOfs (gofs_t ofs, def_t* typ)
146 {
147 	int		i;
148 	ddef_t	*def = NULL;
149 	ddef_t	*d = NULL;
150 
151 	for (i = 0; i < progs->numglobaldefs; i++)
152 	{
153 		d = &pr_globaldefs[i];
154 		if (d->ofs == ofs)
155 		{
156 			def = d;
157 			break;
158 		}
159 	}
160 
161 	if (!def)
162 		return Get_Immediate(ofs);
163 
164 	if (!strcmp(pr_strings + def->s_name, IMMEDIATE_NAME))
165 		return DCC_ValueString ((etype_t)def->type, &pr_globals[ofs]);
166 
167 	if (typ)
168 	{
169 	//	printf("type %s %d\n", pr_strings + def->s_name, typ->type->type);
170 		if (typ->type->type == ev_float && d->type == ev_vector)
171 			def = &pr_globaldefs[i + 1];
172 	}
173 //	printf("found %s\n", pr_strings + def->s_name);
174 	return (pr_strings + def->s_name);
175 }
176 
PR_PrintGlobal(gofs_t ofs,def_t * typ)177 static const char *PR_PrintGlobal (gofs_t ofs, def_t* typ)
178 {
179 	int		i;
180 	ddef_t	*def = NULL;
181 	ddef_t	*d = NULL;
182 
183 	for (i = 0; i < progs->numglobaldefs; i++)
184 	{
185 		d = &pr_globaldefs[i];
186 		if (d->ofs == ofs)
187 		{
188 			def = d;
189 			break;
190 		}
191 	}
192 
193 	if (!def)
194 		return NULL;
195 
196 	if (!strcmp(pr_strings + def->s_name, IMMEDIATE_NAME))
197 		return DCC_ValueString ((etype_t)def->type, &pr_globals[ofs]);
198 
199 	if (typ)
200 	{
201 		if (typ->type->type == ev_float && d->type == ev_vector)
202 			def = &pr_globaldefs[i + 1];
203 	}
204 	return (pr_strings + def->s_name);
205 }
206 
207 
DccStatement(dstatement_t * s)208 static void DccStatement (dstatement_t *s)
209 {
210 	static char	dsline[2048], funcname[512];
211 	const char	*arg1, *arg2, *arg3;
212 	char		a1[1024], a2[1024], a3[1024];
213 	int		nargs, i, j;
214 	dstatement_t	*t, *k;
215 	int		doc, ifc;
216 	unsigned short	tom;
217 	def_t		*typ1 = NULL, *typ2 = NULL, *typ3 = NULL;
218 	ddef_t		*par;
219 	int		op_a, op_b;
220 
221 	a1[0] = a2[0] = a3[0] = dsline[0] = funcname[0] = '\0';
222 
223 	doc = flowinfo[s - pr_statements].do_cnt;
224 	ifc = flowinfo[s - pr_statements].if_cnt;
225 
226 /* use program flow information */
227 	for (i = 0; i < ifc; i++)
228 	{
229 		PR_Print("\n");
230 		lindent--;
231 		PR_Indent();
232 		PR_Print("}\n");
233 	//	printf("entered program flow\n");
234 	}
235 
236 	for (i = 0; i < doc; i++)
237 	{
238 		PR_Indent();
239 		PR_Print("do {\n\n");
240 		lindent++;
241 	}
242 
243 	typ1 = pr_opcodes[s->op].type_a;
244 	typ2 = pr_opcodes[s->op].type_b;
245 	typ3 = pr_opcodes[s->op].type_c;
246 
247 	if (pr_dumpasm)
248 	{
249 		arg1 = PR_PrintGlobal(s->a, typ1);
250 		arg2 = PR_PrintGlobal(s->b, typ2);
251 		arg3 = PR_PrintGlobal(s->c, typ3);
252 		PR_Print("\n%s(%d): %s(%d) %s(%d) %s(%d):\n",
253 			  pr_opcodes[s->op].opname, s->op,
254 			  arg1, s->a, arg2, s->b, arg3, s->c);
255 	}
256 
257 	arg1 = arg2 = arg3 = NULL;
258 
259 	if (s->op == OP_DONE)
260 	{
261 		lindent--;
262 		PR_Indent();
263 		PR_Print("};\n\n");
264 		return;
265 	}
266 	else if (s->op == OP_STATE)
267 	{
268 	}
269 	else if (s->op == OP_RETURN)
270 	{
271 		PR_Indent();
272 		PR_Print("return ");
273 
274 		if (s->a)
275 		{
276 			arg1 = PR_PrintStringAtOfs(s->a, typ1);
277 			PR_Print("( %s )", arg1);
278 		}
279 
280 		PR_Print(";\n");
281 	}
282 	else if ((OP_MUL_F <= s->op && s->op <= OP_SUB_V) ||
283 		 (OP_EQ_F  <= s->op && s->op <= OP_GT   ) ||
284 		 (OP_AND   <= s->op && s->op <= OP_BITOR))
285 	{
286 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
287 		if (arg1)
288 			strcpy(a1, arg1);
289 
290 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
291 		if (arg2)
292 			strcpy(a2, arg2);
293 
294 		arg3 = PR_PrintGlobal(s->c, typ3);
295 		if (arg3)
296 		{
297 			PR_Indent();
298 			PR_Print("%s = %s %s %s;\n", arg3, a1, pr_opcodes[s->op].name, a2);
299 		}
300 		else
301 		{
302 			sprintf(dsline, "(%s %s %s)", a1, pr_opcodes[s->op].name, a2);
303 			Make_Immediate(s->c, dsline);
304 		}
305 	}
306 	else if (OP_LOAD_F <= s->op && s->op <= OP_ADDRESS)
307 	{
308 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
309 		if (arg1)
310 			strcpy(a1, arg1);
311 
312 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
313 		if (arg2)
314 			strcpy(a2, arg2);
315 
316 		arg3 = PR_PrintGlobal(s->c, typ3);
317 		if (arg3)
318 		{
319 			PR_Indent();
320 			PR_Print("%s = %s.%s;\n", arg3, a1, a2);
321 		}
322 		else
323 		{
324 			sprintf(dsline, "%s.%s", a1, a2);
325 		//	printf("%s.%s making immediate at %d\n",a1,a2,s->c);
326 			Make_Immediate(s->c, dsline);
327 		}
328 	}
329 	else if ((OP_STORE_F <= s->op) && (s->op <= OP_STORE_FNC))
330 	{
331 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
332 		if (arg1)
333 			strcpy(a1,arg1);
334 
335 		/*
336 		par = DEC_GetParameter (s->a);
337 		if (par && s->op == OP_STORE_F)
338 		{
339 			if (par->type == ev_vector)
340 				strcat(a1, "_x");
341 		}
342 		*/
343 		arg3 = PR_PrintGlobal(s->b, typ2);
344 		if (arg3)
345 		{
346 			PR_Indent();
347 			PR_Print("%s = %s;\n", arg3, a1);
348 		}
349 		else
350 		{
351 			sprintf(dsline,"%s", a1);
352 			Make_Immediate(s->b, dsline);
353 		}
354 	}
355 	else if ((OP_STOREP_F <= s->op) && (s->op <= OP_STOREP_FNC))
356 	{
357 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
358 		if (arg1)
359 			strcpy(a1, arg1);
360 
361 		par = DEC_GetParameter (s->a);
362 		if (par && s->op == OP_STOREP_F)
363 		{
364 			if (par->type == ev_vector)
365 				strcat(a1, "_x");
366 		}
367 
368 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
369 
370 		PR_Indent();
371 		PR_Print("%s = %s;\n", arg2, a1);
372 	}
373 	else if ((OP_NOT_F <= s->op) && (s->op <= OP_NOT_FNC))
374 	{
375 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
376 		sprintf(dsline, "!%s", arg1);
377 		Make_Immediate(s->c, dsline);
378 	}
379 	else if ((OP_CALL0 <= s->op) && (s->op <= OP_CALL8))
380 	{
381 		nargs = s->op - OP_CALL0;
382 
383 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
384 		if (arg1)
385 			strcpy(a1, arg1);
386 	//	printf("fname: %s %s\n", a1, arg1);
387 
388 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
389 		if (arg2)
390 			strcpy(a2, arg2);
391 
392 		arg3 = PR_PrintStringAtOfs(s->c, typ3);
393 		sprintf(dsline, "%s (", a1);
394 		sprintf(funcname, "%s", a1);
395 		if (arg2)
396 		{
397 			strcat(dsline, " ");
398 			strcat(dsline, a2);
399 			i++;
400 		}
401 
402 		if (arg3 && nargs > 1)
403 		{
404 			size_t	len = strlen(arg3);
405 			strcat(dsline, ", ");
406 			strcat(dsline, arg3);
407 			if (!strcmp(funcname, "WriteCoord") || !strcmp(funcname, "WriteAngle"))
408 			{
409 				if (len >= 2)
410 				{
411 					len -= 2;
412 					if (strcmp(&arg3[len], "_x") &&
413 						!(!strcmp(&arg3[len], "_y") ||
414 						  !strcmp(&arg3[len], "_z") ||
415 						  !strcmp(&arg3[len+1], ")")))
416 					    strcat(dsline, "_x");
417 				}
418 			}
419 		}
420 
421 		for (i = 2; i < nargs; i++)
422 		{
423 			strcat(dsline, ", ");
424 			arg2 = Get_Immediate(OFS_PARM0 + (i * 3));
425 			if (!arg2)
426 				continue;
427 			strcat(dsline, arg2);
428 		}
429 
430 		strcat(dsline, ")");
431 		Make_Immediate(OFS_RETURN, dsline);
432 		j = 1;	/* print now */
433 
434 		for (i = 1; (s + i)->op; i++)
435 		{
436 		//	printf ("\n%d\n", (s + i)->op);
437 			if ((s + i)->op == OP_DONE)
438 				break;
439 
440 			if ((s + i)->op >= OP_RAND0)
441 				break;
442 
443 			if ((s + i)->a == OFS_RETURN ||
444 			    (s + i)->b == OFS_RETURN ||
445 			    (s + i)->c == OFS_RETURN)
446 			{
447 				j = 0;
448 			//	printf("ofs_return is used before another call %d %d %d\n",
449 			//		j, i, (s + i)->op);
450 				break;
451 			}
452 
453 			if (OP_CALL0 <= (s + i)->op && (s + i)->op <= OP_CALL8)
454 			{
455 			//	if (i == 1)
456 			//		j = 0;
457 			//	printf("another call %d  %d %d %d \n",
458 			//		j, i, (s + i)->a, (s + i)->b);
459 				break;
460 			}
461 		}
462 
463 		if (j)
464 		{
465 			PR_Indent();
466 			PR_Print("%s;\n", temp_val[OFS_RETURN]);
467 		}
468 	}
469 	else if (s->op == OP_IF || s->op == OP_IFNOT)
470 	{
471 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
472 		if (arg1)
473 			strcpy(a1, arg1);
474 
475 		if (s->op == OP_IFNOT)
476 		{
477 			op_b = (progs->version == PROG_VERSION_V6) ? (signed short)s->b : s->b;
478 			if (op_b < 1)
479 				COM_Error("Found a negative IFNOT jump.");
480 
481 			/* get instruction right before the target */
482 			t = s + op_b - 1; /* */
483 			tom = t->op;
484 
485 			if (tom != OP_GOTO)
486 			{
487 			/* pure if */
488 				PR_Indent();
489 				PR_Print("if ( %s ) {\n\n", a1);
490 				lindent++;
491 			}
492 			else
493 			{
494 				op_a = (progs->version == PROG_VERSION_V6) ? (signed short)t->a : t->a;
495 				if (op_a > 0)
496 				{
497 				/* ite */
498 					PR_Indent();
499 					PR_Print("if ( %s ) {\n\n", a1);
500 					lindent++;
501 				}
502 				else
503 				{
504 					if (op_a + op_b > 1)
505 					{
506 					/* pure if */
507 						PR_Indent();
508 						PR_Print("if ( %s ) {\n\n", a1);
509 						lindent++;
510 					}
511 					else
512 					{
513 						int		dum = 1;
514 						for (k = t + op_a; k < s; k++)
515 						{
516 							tom = k->op;
517 							if (tom == OP_GOTO || tom == OP_IF || tom == OP_IFNOT)
518 								dum = 0;
519 						}
520 
521 						if (dum)
522 						{
523 						/* while */
524 							PR_Indent();
525 							PR_Print("while ( %s ) {\n\n", a1);
526 							lindent++;
527 						}
528 						else
529 						{
530 						/* pure if */
531 							PR_Indent();
532 							PR_Print("if ( %s ) {\n\n", a1);
533 							lindent++;
534 						}
535 					}
536 				}
537 			}
538 		}
539 		else
540 		{
541 		/* do ... while */
542 			op_b = (progs->version == PROG_VERSION_V6) ? (signed short)s->b : s->b;
543 			if (op_b < 0)
544 			{
545 				lindent--;
546 				PR_Indent();
547 				PR_Print("} while ( %s );\n", a1);
548 			}
549 			else
550 			{
551 				PR_Indent();
552 				PR_Print("if ( !(%s) ) {\n\n", a1);
553 				lindent++;
554 			}
555 		}
556 	}
557 	else if (s->op == OP_GOTO)
558 	{
559 		op_a = (progs->version == PROG_VERSION_V6) ? (signed short)s->a : s->a;
560 		if (op_a > 0)
561 		{
562 		/* else */
563 			lindent--;
564 			PR_Indent();
565 			PR_Print("} else {\n\n");
566 			lindent++;
567 		}
568 		else
569 		{
570 		/* while */
571 			PR_Print("\n");
572 			lindent--;
573 			PR_Indent();
574 			PR_Print("}\n");
575 		}
576 	}
577 	else if ((s->op >= OP_MULSTORE_F && s->op <= OP_SUBSTOREP_V) ||
578 		 (s->op >= OP_BITSET && s->op <= OP_BITCLRP))
579 	{
580 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
581 		if (arg1)
582 			strcpy(a1, arg1);
583 
584 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
585 		if (arg2)
586 			sprintf(dsline, "%s", arg2);
587 
588 		PR_Indent();
589 		PR_Print("%s %s %s;\n", arg2, pr_opcodes[s->op].name, a1);
590 
591 		if (s->c)
592 			Make_Immediate(s->c, dsline);
593 	}
594 	else if (s->op == OP_FETCH_GBL_F || s->op == OP_FETCH_GBL_V)
595 	{
596 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
597 		if (arg1)
598 			strcpy(a1, arg1);
599 
600 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
601 		if (arg2)
602 			strcpy(a2, arg2);
603 
604 		arg3 = PR_PrintStringAtOfs(s->c, typ3);
605 		if (arg3)
606 		{
607 			PR_Indent();
608 			PR_Print("%s = %s->%s;\n", arg3, a2, a1);
609 		}
610 		else
611 		{
612 			sprintf(dsline, "(%s->%s)", a1, a2);
613 			Make_Immediate(s->c, dsline);
614 		}
615 	}
616 	else if (s->op == OP_CSTATE)
617 	{
618 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
619 		if (arg1)
620 			strcpy(a1, arg1);
621 
622 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
623 		PR_Indent();
624 		PR_Print("AdvanceFrame( %s, %s);\n", a1, arg2);
625 	}
626 	else if (s->op == OP_THINKTIME)
627 	{
628 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
629 		if (arg1)
630 			strcpy(a1, arg1);
631 
632 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
633 		PR_Indent();
634 		PR_Print("AdvanceThinkTime(%s,%s);\n", a1, arg2);
635 	}
636 	else if (s->op == OP_RAND0)
637 	{
638 		sprintf(dsline,"random()");
639 		Make_Immediate(OFS_RETURN, dsline);
640 	}
641 	else if (s->op == OP_RAND1)
642 	{
643 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
644 		if (arg1)
645 			strcpy(a1, arg1);
646 
647 		sprintf(dsline, "random(%s)", a1);
648 		Make_Immediate(OFS_RETURN, dsline);
649 	}
650 	else if (s->op == OP_RAND2)
651 	{
652 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
653 		if (arg1)
654 			strcpy(a1, arg1);
655 
656 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
657 		sprintf(dsline, "random(%s,%s)", a1, arg2);
658 		Make_Immediate(OFS_RETURN, dsline);
659 	}
660 	else if (s->op == OP_RANDV0)
661 	{
662 		sprintf(dsline,"random( )");
663 		Make_Immediate(OFS_RETURN, dsline);
664 	}
665 	else if (s->op == OP_RANDV1)
666 	{
667 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
668 		if (arg1)
669 			strcpy(a1, arg1);
670 
671 		sprintf(dsline, "random(%s)", a1);
672 		Make_Immediate(OFS_RETURN, dsline);
673 	}
674 	else if (s->op == OP_RANDV2)
675 	{
676 		arg1 = PR_PrintStringAtOfs(s->a, typ1);
677 		if (arg1)
678 			strcpy(a1, arg1);
679 
680 		arg2 = PR_PrintStringAtOfs(s->b, typ2);
681 		sprintf(dsline, "random(%s,%s)", a1, arg2);
682 		Make_Immediate(OFS_RETURN, dsline);
683 	}
684 	else
685 	{
686 		PR_Print("\n/* ERROR: UNKNOWN COMMAND */\n OP: %d  ", s->op);
687 		arg1 = PR_PrintStringAtOfs(s->a, NULL);
688 		arg2 = PR_PrintStringAtOfs(s->b, NULL);
689 		arg3 = PR_PrintStringAtOfs(s->c, NULL);
690 		if (progs->version == PROG_VERSION_V6)
691 		{
692 			PR_Print("a: %s(%d)", arg1, (signed short)s->a);
693 			PR_Print(" b: %s(%d)", arg2, (signed short)s->b);
694 			PR_Print(" c: %s(%d)\n", arg3, (signed short)s->c);
695 		}
696 		else /* PROG_VERSION_V7 */
697 		{
698 			PR_Print("a: %s(%d)", arg1, s->a);
699 			PR_Print(" b: %s(%d)", arg2, s->b);
700 			PR_Print(" c: %s(%d)\n", arg3, s->c);
701 		}
702 	}
703 }
704 
Make_Immediate(gofs_t ofs,const char * s)705 static void Make_Immediate (gofs_t ofs, const char *s)
706 {
707 	if (ofs >= progs->numglobals) /* happens with opcodes that DHCC doesn't know, i.e. switches. */
708 	{
709 	//	printf ("%s: ofs %d is past numpr_globals %d (cfunc->parm_start: %d, cfunc->locals: %d)\n",
710 	//			__thisfunc__, ofs, progs->numglobals, cfunc->parm_start, cfunc->locals);
711 		return;
712 	}
713 	if (temp_val[ofs])
714 		free(temp_val[ofs]);
715 	temp_val[ofs] = SafeStrdup(s);
716 }
717 
Get_Immediate(gofs_t ofs)718 static char *Get_Immediate (gofs_t ofs)
719 {
720 	if (ofs >= progs->numglobals) /* happens with opcodes that DHCC doesn't know, i.e. switches. */
721 	{
722 	//	printf ("%s: ofs %d is past numpr_globals %d (cfunc->parm_start: %d, cfunc->locals: %d)\n",
723 	//			__thisfunc__, ofs, progs->numglobals, cfunc->parm_start, cfunc->locals);
724 		return NULL;
725 	}
726 
727 	return temp_val[ofs];
728 }
729 
Clear_Immediates(void)730 static void Clear_Immediates (void)
731 {
732 	int	i;
733 	for (i = 0; i < progs->numglobals; i++)
734 	{
735 		if (temp_val[i])
736 		{
737 			free(temp_val[i]);
738 			temp_val[i] = NULL;
739 		}
740 	}
741 }
742 
743 
AddProgramFlowInfo(dfunction_t * df)744 static void AddProgramFlowInfo (dfunction_t *df)
745 {
746 	dstatement_t	*ds, *ts;
747 	unsigned short	dom, tom;
748 	dstatement_t	*k;
749 	int		op_a, op_b;
750 
751 	ds = pr_statements + df->first_statement;
752 
753 	while (1)
754 	{
755 		dom = ds->op;
756 		if (!dom)
757 		{
758 			break;
759 		}
760 		else if (dom == OP_GOTO)
761 		{
762 		/* check for i-t-e */
763 			op_a = (progs->version == PROG_VERSION_V6) ? (signed short)ds->a : ds->a;
764 			if (op_a > 0)
765 			{
766 				ts = ds + op_a;
767 				/* mark the end of a if/ite construct */
768 				flowinfo[ts - pr_statements].if_cnt++;
769 			}
770 		}
771 		else if (dom == OP_IFNOT)
772 		{
773 		/* check for pure if */
774 			op_b = (progs->version == PROG_VERSION_V6) ? (signed short)ds->b : ds->b;
775 			ts  = ds + op_b; /* FIXME: ds->b < 0 possible? */
776 			tom = (ts - 1)->op;
777 
778 			if (tom != OP_GOTO)
779 			{
780 				/* mark the end of a if/ite construct */
781 				flowinfo[ts - pr_statements].if_cnt++;
782 			}
783 			else
784 			{
785 				op_a = (progs->version == PROG_VERSION_V6) ? (signed short)((ts - 1)->a) : (ts - 1)->a;
786 				if (op_a < 0)
787 				{
788 					if (op_a + op_b > 1)
789 					{ /* pure if */
790 						/* mark the end of a if/ite construct */
791 						flowinfo[ts - pr_statements].if_cnt++;
792 					}
793 					else
794 					{
795 						int	dum = 1;
796 						for (k = (ts - 1) + op_a; k < ds; k++)
797 						{
798 							tom = k->op;
799 							if (tom == OP_GOTO || tom == OP_IF || tom == OP_IFNOT)
800 								dum = 0;
801 						}
802 						if (!dum)
803 						{ /* pure if */
804 							/* mark the end of a if/ite construct */
805 							flowinfo[ts - pr_statements].if_cnt++;
806 						}
807 					}
808 				}
809 			}
810 		}
811 		else if (dom == OP_IF)
812 		{
813 			op_b = (progs->version == PROG_VERSION_V6) ? (signed short)ds->b : ds->b;
814 			ts = ds + op_b;
815 			if (op_b < 0)
816 			{
817 				/* mark the start of a do construct */
818 				flowinfo[ts - pr_statements].do_cnt++;
819 			}
820 			else
821 			{
822 				/* mark the end of a if/ite construct */
823 				flowinfo[ts - pr_statements].if_cnt++;
824 			}
825 		}
826 
827 		ds++;
828 	}
829 }
830 
831 
PR_Indent(void)832 static void PR_Indent (void)
833 {
834 	int	i;
835 
836 	if (lindent < 0)
837 		lindent = 0;
838 
839 	for (i = 0; i < lindent; i++)
840 	{
841 		PR_Print("   ");
842 	}
843 }
844 
PR_Locals(dfunction_t * df)845 static void PR_Locals (dfunction_t *df)
846 {
847 	int	start, i, j, k;
848 	ddef_t	*par;
849 
850 	start = df->parm_start;
851 	i = df->numparms;
852 
853 	for (j = k = 0; j < i; j++)
854 		k += df->parm_size[j];
855 
856 	start += k;
857 
858 	for (j = start; j < df->parm_start + df->locals; j++)
859 	{
860 		PR_Indent();
861 		par = DEC_GetParameter (j);
862 		if (par)
863 		{
864 			if (par->type == ev_void  || par->type == ev_void ||
865 			    par->type == ev_field || par->type == ev_function ||
866 			    par->type == ev_pointer)
867 			{
868 				continue;
869 			}
870 
871 			if (!strcmp(IMMEDIATE_NAME, pr_strings + par->s_name))
872 				continue;
873 
874 			PR_Print("local ");
875 
876 			switch (par->type)
877 			{
878 			case ev_string:
879 				PR_Print("string");
880 				break;
881 			case ev_void:
882 				PR_Print("void");
883 				break;
884 			case ev_float:
885 				PR_Print("float");
886 				break;
887 			case ev_vector:
888 				PR_Print("vector");
889 				j += 2;
890 				break;
891 			case ev_entity:
892 				PR_Print("entity");
893 				break;
894 			case ev_field:
895 				PR_Print("ev_field");
896 				break;
897 			case ev_function:
898 				PR_Print("void()");
899 				break;
900 			case ev_pointer:
901 				PR_Print("ev_pointer");
902 				break;
903 			}
904 
905 			PR_Print(" %s", pr_strings + par->s_name);
906 
907 			if (par->type == ev_float || par->type == ev_vector)
908 				PR_Print(" = %s", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs]));
909 
910 			PR_Print(";\n");
911 		}
912 	}
913 }
914 
915 
PR_FunctionHeader(dfunction_t * df)916 static void PR_FunctionHeader (dfunction_t *df)
917 {
918 	int	j, start;
919 	ddef_t	*par;
920 	char	linetxt[512];
921 	unsigned short	t1;
922 
923 	if (func_headers[df - pr_functions])	/* already done */
924 		return;
925 
926 	if (df->first_statement < 0)
927 	{ /* builtin */
928 		FindBuiltinParameters(df - pr_functions);
929 		return;
930 	}
931 
932 	/* get return type */
933 	linetxt[0] = '\0';
934 	t1 = GetReturnType(df - pr_functions);
935 
936 	switch (t1)
937 	{
938 	case ev_string:
939 		sprintf(linetxt, "string ");
940 		break;
941 	case ev_void:
942 		sprintf(linetxt, "void ");
943 		break;
944 	case ev_float:
945 		sprintf(linetxt, "float ");
946 		break;
947 	case ev_vector:
948 		sprintf(linetxt, "vector ");
949 		break;
950 	case ev_entity:
951 		sprintf(linetxt, "entity ");
952 		break;
953 	case ev_field:
954 		sprintf(linetxt, "ev_field ");
955 		break;
956 	case ev_function:
957 		sprintf(linetxt, "void() ");
958 		break;
959 	case ev_pointer:
960 		sprintf(linetxt, "ev_pointer ");
961 		break;
962 	default:
963 		sprintf(linetxt, "void ");
964 		break;
965 	}
966 
967 	/* print parameters */
968 	strcat(linetxt, " (");
969 
970 	start = df->parm_start;
971 
972 	for (j = 0; j < df->numparms; j++)
973 	{
974 		par = DEC_GetParameter (start);
975 
976 		if (par)
977 		{
978 			switch (par->type)
979 			{
980 			case ev_string:
981 				strcat(linetxt, "string ");
982 				break;
983 			case ev_void:
984 				strcat(linetxt, "void ");
985 				break;
986 			case ev_float:
987 				strcat(linetxt, "float ");
988 				break;
989 			case ev_vector:
990 				strcat(linetxt, "vector ");
991 				break;
992 			case ev_entity:
993 				strcat(linetxt, "entity ");
994 				break;
995 			case ev_field:
996 				strcat(linetxt, "ev_field ");
997 				break;
998 			case ev_function:
999 				strcat(linetxt, "void() ");
1000 				break;
1001 			case ev_pointer:
1002 				strcat(linetxt, "ev_pointer ");
1003 				break;
1004 			}
1005 
1006 			strcat(linetxt, pr_strings + par->s_name);
1007 		}
1008 		else
1009 		{
1010 			sprintf(linetxt, "void unknown ");
1011 		}
1012 
1013 		if (j < (df->numparms - 1))
1014 			strcat(linetxt, ",");
1015 
1016 		start += df->parm_size[j];
1017 	}
1018 
1019 	strcat(linetxt, ")");
1020 	func_headers[df - pr_functions] = SafeStrdup(linetxt);
1021 }
1022 
1023 
PR_Print(const char * s,...)1024 static void PR_Print (const char *s,...)
1025 {
1026 	va_list argptr;
1027 
1028 	va_start (argptr, s);
1029 	vfprintf (PR_FILE, s, argptr);
1030 	va_end (argptr);
1031 }
1032 
GetReturnType(int func)1033 static unsigned short GetReturnType (int func)
1034 {
1035 	int		i, j;
1036 	ddef_t		*par = NULL;
1037 	dstatement_t	*ds, *di;
1038 	dfunction_t	*df;
1039 	const char	*arg1;
1040 	unsigned short	rtype[2] = {ev_void, ev_void};
1041 	def_t		*type1;
1042 
1043 	if (func == 0)
1044 		return ev_void;
1045 
1046 	df = pr_functions + func;
1047 	ds = pr_statements + df->first_statement;
1048 
1049 	if (df->first_statement < 0)
1050 	{
1051 	/* ??? */
1052 	}
1053 
1054 	j = 0;
1055 	while (1)
1056 	{
1057 		if (j > 1)
1058 			break;
1059 
1060 		if (ds->op == OP_DONE)
1061 			break;
1062 
1063 		if (ds->op == OP_RETURN)
1064 		{ /* find 2 different returns if possible just to be certain (ie: findtarget) */
1065 			j++; /* we do come here with j == 1 already.  put j > 1 checks below. */
1066 			if (ds->a != 0)
1067 			{
1068 				if (ds->a == OFS_RETURN)
1069 				{
1070 					di = ds - 1;
1071 					while ((di - pr_statements) >= df->first_statement)
1072 					{	/* that stupid equal, what a bitch */
1073 						if (OP_CALL0 <= di->op && di->op <= OP_CALL8)
1074 						{
1075 							type1 = pr_opcodes[di->op].type_a;
1076 							arg1 = PR_PrintStringAtOfs(di->a, type1);
1077 							if (!arg1)
1078 								COM_Error("function name not found!!!\n");
1079 							i = DEC_GetFunctionIdxByName(arg1);
1080 							if (i == 0)
1081 								break;
1082 							if (i != func)
1083 							{
1084 								if (j < 2)
1085 									rtype[j] = GetReturnType(i);
1086 								/* else: array out of bounds */
1087 								break;
1088 							}
1089 							else
1090 							{
1091 								j--;
1092 								break;
1093 							}
1094 						} /* end if call */
1095 						else if (OP_RAND0 <= di->op && di->op <= OP_RAND2)
1096 						{
1097 							if (j < 2)
1098 								rtype[j] = ev_float;
1099 							/* else: array out of bounds */
1100 							break;
1101 						}
1102 						else if (OP_RANDV0 <= di->op && di->op <= OP_RANDV2)
1103 						{
1104 							if (j < 2)
1105 								rtype[j] = ev_vector;
1106 							/* else: array out of bounds */
1107 							break;
1108 						}
1109 
1110 						di--;
1111 					} /* end while ofs_return */
1112 				}
1113 				else
1114 				{
1115 					if (j > 1)
1116 						break;	/* array out of bounds */
1117 					par = DEC_GetParameter (ds->a);
1118 					if (par)
1119 					{
1120 						rtype[j] = par->type;
1121 					}
1122 					else
1123 					{
1124 					/* find the op where the reg was created,
1125 					 * it can tell what the val is */
1126 						rtype[j] = pr_opcodes[ds->op].type_a->type->type;
1127 						if (rtype[j] == ev_pointer)
1128 						{
1129 							rtype[j] = BackBuildReturnType(df, ds, ds->a);
1130 						}
1131 					}
1132 				}
1133 			}
1134 			else
1135 			{
1136 				if (j > 1)
1137 					break;	/* array out of bounds */
1138 				rtype[j] = ev_void;
1139 			}
1140 		}
1141 
1142 		ds++;
1143 	}
1144 
1145 	if ((rtype[0] != rtype[1]) && (rtype[0] == ev_void))
1146 		rtype[0] = rtype[1];
1147 
1148 	return rtype[0];
1149 }
1150 
1151 #if 0	/* this is unused */
1152 static unsigned short OP_StoreValue (dstatement_t *ds)
1153 {
1154 	switch (ds->op)
1155 	{
1156 	case OP_CALL0:
1157 	case OP_CALL1:
1158 	case OP_CALL2:
1159 	case OP_CALL3:
1160 	case OP_CALL4:
1161 	case OP_CALL5:
1162 	case OP_CALL6:
1163 	case OP_CALL7:
1164 	case OP_CALL8:
1165 		return ev_function;
1166 
1167 	case OP_NOT_V:
1168 	case OP_STORE_V:
1169 	case OP_LOAD_V:
1170 	case OP_NE_V:
1171 	case OP_EQ_V:
1172 	case OP_SUB_V:
1173 	case OP_ADD_V:
1174 	case OP_MUL_V:
1175 	case OP_MUL_FV:
1176 	case OP_MUL_VF:
1177 	case OP_STOREP_V:
1178 		return ev_vector;
1179 
1180 	case OP_NE_F:
1181 	case OP_EQ_F:
1182 	case OP_MUL_F:
1183 	case OP_DIV_F:
1184 	case OP_ADD_F:
1185 	case OP_SUB_F:
1186 	case OP_LE:
1187 	case OP_GE:
1188 	case OP_LT:
1189 	case OP_GT:
1190 	case OP_LOAD_F:
1191 	case OP_STORE_F:
1192 	case OP_NOT_F:
1193 	case OP_STOREP_F:
1194 	case OP_IF:
1195 	case OP_IFNOT:
1196 	case OP_STATE:
1197 	case OP_AND:
1198 	case OP_OR:
1199 	case OP_BITAND:
1200 	case OP_BITOR:
1201 		return ev_float;
1202 
1203 	case OP_EQ_S:
1204 	case OP_NE_S:
1205 	case OP_LOAD_S:
1206 	case OP_STORE_S:
1207 	case OP_STOREP_S:
1208 	case OP_NOT_S:
1209 		return ev_string;
1210 
1211 	case OP_NE_E:
1212 	case OP_EQ_E:
1213 	case OP_LOAD_ENT:
1214 	case OP_STORE_ENT:
1215 	case OP_NOT_ENT:
1216 	case OP_STOREP_ENT:
1217 		return ev_entity;
1218 
1219 	case OP_EQ_FNC:
1220 	case OP_NE_FNC:
1221 	case OP_LOAD_FNC:
1222 	case OP_STORE_FNC:
1223 	case OP_STOREP_FNC:
1224 		return ev_function;
1225 
1226 	case OP_LOAD_FLD:
1227 	case OP_ADDRESS:
1228 	case OP_STORE_FLD:
1229 	case OP_STOREP_FLD:
1230 		return ev_field;
1231 
1232 	case OP_RETURN:
1233 	case OP_NOT_FNC:
1234 	case OP_DONE:
1235 	case OP_GOTO:
1236 		return ev_void;
1237 	}
1238 
1239 	return ev_void;
1240 }
1241 #endif	/* end of unused */
1242 
PR_GetField(const char * name,ddef_t * dd)1243 static ddef_t *PR_GetField (const char *name, ddef_t *dd)
1244 {
1245 	int	i;
1246 	ddef_t	*d;
1247 
1248 	for (i = 1; i < progs->numfielddefs; i++)
1249 	{
1250 		d = &pr_fielddefs[i];
1251 		if (!strcmp(pr_strings + d->s_name, name))
1252 		{
1253 		//	printf("%s %d %d\n", name, dd ? dd->ofs : 0, d ? d->ofs : 0);
1254 			return d;
1255 		}
1256 	}
1257 
1258 	return NULL;
1259 }
1260 
1261 
PR_FieldIsUnique(ddef_t * dd)1262 static ddef_t *PR_FieldIsUnique (ddef_t *dd)
1263 {
1264 	int	i;
1265 	ddef_t	*d;
1266 
1267 	for (i = 1; i < progs->numfielddefs; i++)
1268 	{
1269 		d = &pr_fielddefs[i];
1270 		if (d->ofs == dd->ofs)
1271 		{
1272 			if (d->type == ev_vector && dd - 1 == d)
1273 				return dd;
1274 		//	printf("%s %d %d\n", dd ? pr_strings + dd->s_name : "null", dd ? dd->ofs : 0, d ? d->ofs : 0);
1275 			return d;
1276 		}
1277 	}
1278 
1279 	return NULL;
1280 }
1281 
1282 
Dcc_Functions(void)1283 static void Dcc_Functions (void)
1284 {
1285 	int		i;
1286 	dfunction_t	*df;
1287 	char	fname[1024], *p;
1288 	FILE		*prgs;
1289 
1290 	prgs = fopen("progs.src","w");
1291 	if (!prgs)
1292 		COM_Error("unable to open progs.src!!!\n");
1293 
1294 	fprintf(prgs, "%s", "progs.dat\n\n");
1295 
1296 	for (i = 1; i < progs->numfunctions; i++)
1297 	{
1298 		df = pr_functions + i;
1299 
1300 		if (FILE_NUM_FOR_NAME)
1301 			sprintf (fname, "%d.hc", df->s_file);
1302 		else	sprintf (fname, "%s", pr_strings + df->s_file);
1303 		/* unixify the path, */
1304 		p = fname;
1305 		while (*p)
1306 		{
1307 			if (*p == '\\')
1308 				*p = '/';
1309 			++p;
1310 		}
1311 		/* create parent directories, if any */
1312 		CreatePath(fname);
1313 
1314 		if (! DEC_AlreadySeen(fname))
1315 		{
1316 			fprintf(prgs, "%s\n", fname);
1317 			printf("decompiling %s\n", fname);
1318 		}
1319 
1320 		PR_FILE = fopen(fname, "a+");
1321 		if (PR_FILE == NULL)
1322 		{
1323 			PR_FILE = stdout;
1324 			COM_Error("unable to open %s\n", fname);
1325 		}
1326 
1327 		PR_PrintFunction(pr_strings + df->s_name);
1328 		fclose(PR_FILE);
1329 		PR_FILE = stdout;
1330 	}
1331 
1332 	fclose(prgs);
1333 }
1334 
1335 
CalcArraySize(int j,int end)1336 static int CalcArraySize (int j, int end)
1337 {
1338 	ddef_t	*par;
1339 
1340 	if (j == end)
1341 		return 0;
1342 
1343 	for (j++; j < end; j++)
1344 	{
1345 		par = DEC_GetParameter (j);
1346 		if (par && strcmp(pr_strings + par->s_name, IMMEDIATE_NAME))
1347 		{
1348 		//	printf("next is %s at %d\n", pr_strings + par->s_name, par->ofs);
1349 			return par->ofs;
1350 		}
1351 	}
1352 
1353 //	printf("can not find next %d %d!!!!!!!!!!!!!!!!!!!!\n", j, end);
1354 	return j;
1355 }
1356 
1357 
PR_InitValues(ddef_t * par,int size)1358 static void PR_InitValues (ddef_t *par, int size)
1359 {
1360 	int	j;
1361 
1362 //	printf("size %d\n", size);
1363 
1364 	if (size > 1)
1365 	{
1366 		PR_Print("{ %s,\n", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs]));
1367 	}
1368 	else
1369 	{
1370 		PR_Print(" %s;\n", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs]));
1371 		return;
1372 	}
1373 
1374 	lindent++;
1375 
1376 	for (j = 1; j < size; j++)
1377 	{
1378 		PR_Indent();
1379 		if (j < size - 1)
1380 		{
1381 			if (! (j & 0x3))
1382 				PR_Print(" %s,\n", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs + (j*type_size[par->type])]));
1383 			else	PR_Print(" %s,",   DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs + (j*type_size[par->type])]));
1384 		}
1385 		else
1386 		{
1387 			PR_Print(" %s", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs + (j*type_size[par->type])]));
1388 		}
1389 	}
1390 
1391 	PR_Print("};\n");
1392 	lindent--;
1393 }
1394 
1395 
PR_LocalGlobals(void)1396 static void PR_LocalGlobals (void)
1397 {
1398 	int		i, j, ps, cnt = 0;
1399 	int		start, end, bsize;
1400 	dfunction_t	*df, *dfpred;
1401 	ddef_t		*par;
1402 //	ddef_t		*par2;
1403 	ddef_t		*ef;
1404 	const char	*arg2;
1405 
1406 	printf("finding declared globals:.");
1407 
1408 	df = cfunc;
1409 	dfpred = df - 1;
1410 
1411 	for (j = 0, ps = 0; j < dfpred->numparms; j++)
1412 		ps += dfpred->parm_size[j];
1413 
1414 	start = dfpred->parm_start + dfpred->locals + ps;
1415 
1416 	if (dfpred->first_statement < 0 && df->first_statement > 0)
1417 		start -= 1;
1418 
1419 	if (start == 0)
1420 		start = 1;
1421 
1422 //	printf("starting at %d ending at %d\n", start, end);
1423 
1424 	end = df->parm_start;
1425 
1426 	for (j = start; j < end; j++)
1427 	{
1428 		par = DEC_GetParameter (j);
1429 	//	par2 = DEC_GetParameter (j+1);
1430 		if (! (j & 0xf))
1431 			printf(".");
1432 
1433 		if (!par)
1434 			cnt++;
1435 
1436 		if (par/* && strcmp(pr_strings + par->s_name, IMMEDIATE_NAME)*/)
1437 		{
1438 		//	printf("cnt is %d\n", cnt);
1439 			cnt = 0;
1440 			bsize = CalcArraySize(j, end);
1441 
1442 			par->type &= ~DEF_SAVEGLOBAL;
1443 
1444 		//	printf("%s type: %d ofs: %d par2: %d bsize: %d\n",
1445 		//		  pr_strings + par->s_name, par->type,
1446 		//		  par->ofs, par2 ? (par2->ofs-par->ofs) : -1,
1447 		//		  bsize-par->ofs);
1448 
1449 			if (par->type == ev_function)
1450 			{
1451 				if (strcmp(pr_strings + par->s_name, IMMEDIATE_NAME) == 0)
1452 					continue;
1453 				if (strcmp(pr_strings + par->s_name, pr_strings + cfunc->s_name) == 0)
1454 					continue;
1455 				i = DEC_GetFunctionIdxByName(pr_strings + par->s_name);
1456 				/* check for i == 0 here ???? */
1457 				PR_FunctionHeader(pr_functions + i);
1458 				PR_Print("%s%s;\n", func_headers[i],pr_strings + (pr_functions + i)->s_name);
1459 			}
1460 			else if (par->type != ev_pointer)
1461 			{
1462 				if (strcmp(pr_strings + par->s_name, IMMEDIATE_NAME) == 0)
1463 					continue;
1464 				if (par->type == ev_field)
1465 				{
1466 					ef = PR_GetField(pr_strings + par->s_name, par);
1467 					if (!ef)
1468 						COM_Error("Could not locate a field named \"%s\"", pr_strings + par->s_name);
1469 					i = (ef->type & ~DEF_SAVEGLOBAL);
1470 					if (i == ev_vector)
1471 						j += 3;
1472 					if (i == ev_function)
1473 					{
1474 						arg2 = GetFieldFunctionHeader(pr_strings + ef->s_name);
1475 						GFFH_depth = 0;
1476 					//	printf("function .%s %s;\n", arg2, pr_strings + ef->s_name);
1477 						PR_Print(".%s %s;\n", arg2, pr_strings + ef->s_name);
1478 					}
1479 					else
1480 					{
1481 					//	printf("variable %d .%s %s;\n", i, type_names[i], pr_strings + ef->s_name);
1482 						par = PR_FieldIsUnique(ef);
1483 						if (par == ef)
1484 							PR_Print(".%s %s;\n", type_names[i], pr_strings + ef->s_name);
1485 						else
1486 							PR_Print(".%s %s alias %s;\n", type_names[i], pr_strings + ef->s_name, pr_strings + par->s_name);
1487 					}
1488 				}
1489 				else
1490 				{
1491 					bsize = (bsize - par->ofs) / type_size[par->type];
1492 					if (!par->ofs || bsize - 1 < *(int *)&pr_globals[par->ofs - 1])
1493 					{
1494 					//	printf("bsize %d %d\n", bsize, *(int *)&pr_globals[par->ofs - 1]);
1495 						bsize = 1;
1496 					}
1497 				 	if (bsize != 1)
1498 					{
1499 						bsize = *(int *)&pr_globals[par->ofs - 1] + 1;
1500 					}
1501 					if (par->type == ev_vector)
1502 						j += 2;
1503 					if (par->type == ev_entity || par->type == ev_void)
1504 					{
1505 						if (!strcmp(pr_strings + par->s_name, "end_sys_fields"))
1506 							printassign = true;
1507 						PR_Print("%s %s;\n", type_names[par->type], pr_strings + par->s_name);
1508 					}
1509 					else
1510 					{
1511 						if (pr_dumpasm  ||
1512 						    printassign ||
1513 						   !strcmp(pr_strings + par->s_name, "string_null"))
1514 						{
1515 							if (bsize < 2)
1516 								PR_Print("%s %s   = ", type_names[par->type], pr_strings + par->s_name);
1517 							else
1518 								PR_Print("%s %s [%d]   = ", type_names[par->type], pr_strings + par->s_name, bsize);
1519 							PR_InitValues(par, bsize);
1520 						}
1521 						else
1522 						{
1523 							PR_Print("%s %s;\n", type_names[par->type], pr_strings + par->s_name);
1524 						}
1525 					}
1526 				}
1527 			}
1528 		}
1529 	}
1530 
1531 	printf("\n");
1532 }
1533 
1534 
GetFieldFunctionHeader(const char * s_name)1535 static const char *GetFieldFunctionHeader (const char *s_name)
1536 {
1537 	int		i, j = 0;
1538 	dstatement_t	*d;
1539 //	const char	*arg1;
1540 	const char	*arg2, *arg3;
1541 	def_t		*typ;
1542 
1543 	if (++GFFH_depth > GFFH_MAX_DEPTH) /* see below */
1544 	{
1545 	//	printf("\n%s: MAX_DEPTH reached for \"%s\", returning void ()\n",
1546 	//						__thisfunc__, s_name);
1547 		return "void  ()";
1548 	}
1549 
1550 	for (i = 1; i < progs->numstatements; i++)
1551 	{
1552 		d = pr_statements + i;
1553 
1554 		if (d->op == OP_ADDRESS)
1555 		{
1556 		//	typ  = pr_opcodes[d->op].type_a;
1557 		//	arg1 = PR_PrintGlobal(d->a, typ);
1558 			typ  = pr_opcodes[d->op].type_b;
1559 			arg2 = PR_PrintGlobal(d->b, typ);
1560 
1561 			if (arg2)
1562 			{
1563 				if (!strcmp(s_name, arg2))
1564 				{
1565 					if ((d + 1)->op == OP_STOREP_FNC)
1566 					{
1567 						d++;
1568 						typ  = pr_opcodes[d->op].type_a;
1569 						arg3 = PR_PrintGlobal(d->a, typ);
1570 						if (!arg3)
1571 							continue;
1572 						j = DEC_GetFunctionIdxByName(arg3);
1573 						/* check for j == 0 here ???? */
1574 						PR_FunctionHeader(pr_functions + j);
1575 						if (strcmp("void  ()", func_headers[j]))
1576 							return func_headers[j];
1577 						/* if void (), continue checking just to be certain (ie: th_pain) */
1578 
1579 						/* NOTE:  When decompiling progs.dat of hcbots, this
1580 						 * results in an infinite recursion below by the function
1581 						 * calling itself with "think" and "th_stand" as the
1582 						 * arguments alternating between each succession,
1583 						 * hence the MAX_DEPTH check at the function's entrance.
1584 						 * I don't have a better solution so far.. - O.S. */
1585 					}
1586 
1587 					if ((d + 1)->op == OP_LOAD_FNC && (d + 2)->op == OP_STOREP_FNC)
1588 					{
1589 						d++;
1590 					//	typ  = pr_opcodes[d->op].type_a;
1591 					//	arg1 = PR_PrintGlobal(d->a, typ);
1592 						typ  = pr_opcodes[d->op].type_b;
1593 						arg2 = PR_PrintGlobal(d->b, typ);
1594 						if (!arg2)
1595 							continue;
1596 						if (strcmp(s_name, arg2))
1597 							return GetFieldFunctionHeader(arg2);
1598 					}
1599 				}
1600 			}
1601 		}
1602 	}
1603 
1604 //	printf ("returning found statement %5d %s %s\n", i, arg3, func_headers[j]);
1605 
1606 	if (j == 0)
1607 		return "void  ()";
1608 
1609 	return func_headers[j];
1610 }
1611 
1612 
FindBuiltinParameters(int func)1613 static void FindBuiltinParameters (int func)
1614 {
1615 	int		i, j;
1616 	unsigned short	type[9];
1617 	dstatement_t	*ds, *dsf = NULL;
1618 	dfunction_t	*df, *dft = NULL;
1619 	const char	*arg1;
1620 	char		sname[512], plist[512], parm[128];
1621 
1622 	if (func_headers[func])
1623 		return;
1624 
1625 	df = pr_functions + func;
1626 
1627 //	printf("%s %d\n", pr_strings + df->s_name, df->numparms);
1628 	printf("looking for builtin %s...: ", pr_strings + df->s_name);
1629 
1630 	for (i = 1; i < progs->numfunctions; i++)
1631 	{
1632 		if (! (i & 0xf))
1633 			printf(".");	/* let'em know its working, not hanging */
1634 
1635 		j = (pr_functions + i)->first_statement;
1636 		if (j < 0)
1637 			continue;
1638 
1639 		ds = pr_statements + j;
1640 
1641 		while (ds && ds->op)
1642 		{
1643 			if (ds->op >= OP_CALL0 && ds->op <= OP_CALL8)
1644 			{
1645 				arg1 = PR_PrintStringAtOfs(ds->a, 0);
1646 
1647 				if (arg1)
1648 				{
1649 					if (!strcmp(pr_strings + df->s_name, arg1))
1650 					{
1651 						dsf = ds;
1652 						dft = pr_functions + i;
1653 						printf("\nfound!!\ndetermining parameters\n");
1654 						break;
1655 					}
1656 				}
1657 			}
1658 
1659 			arg1 = NULL;
1660 			ds++;
1661 		//	ds = pr_statements + (pr_functions + i)->first_statement + j;
1662 		}
1663 
1664 		if (dsf)
1665 			break;
1666 	}
1667 
1668 	if (!dsf)
1669 	{
1670 		printf("NOT found!!\nsetting parameters to void\n");
1671 		func_headers[func] = SafeStrdup("void ()");
1672 		return;
1673 	}
1674 
1675 	j = ((dsf->op - OP_CALL0));
1676 	type[8] = ev_void;
1677 
1678 	for (ds = dsf + 1; ds && ds->op; ds++)
1679 	{
1680 		if ((ds->op >= OP_CALL0 && ds->op <= OP_CALL8) || ds->op >= OP_RAND0)
1681 			break;
1682 
1683 		if (ds->a == OFS_RETURN)
1684 		{
1685 		//	printf("%d %d %d %d 1 rt %d %d\n", ds->op, ds->a, ds->b, ds->c, pr_opcodes[ds->op].type_a->type->type, ev_pointer);
1686 			if (ds->c)
1687 			{
1688 				type[8] = pr_opcodes[ds->op].type_c->type->type;
1689 				if (type[8] == ev_pointer)
1690 					type[8] = BackBuildReturnType(dft, ds, ds->c);
1691 			}
1692 			else
1693 			{
1694 				type[8] = pr_opcodes[ds->op].type_b->type->type;
1695 				if (type[8] == ev_pointer)
1696 					type[8] = BackBuildReturnType(dft, ds, ds->b);
1697 			}
1698 			break;
1699 		}
1700 
1701 		if (ds->b == OFS_RETURN)
1702 		{
1703 		//	printf("%d %d %d %d 2 rt %d\n", ds->op, ds->a, ds->b, ds->c, pr_opcodes[ds->op].type_b->type->type);
1704 			type[8] = pr_opcodes[ds->op].type_b->type->type;
1705 			if (type[8] == ev_pointer)
1706 				type[8] = BackBuildReturnType(dft, ds, ds->b);
1707 			break;
1708 		}
1709 
1710 		if (ds->c == OFS_RETURN)
1711 		{
1712 		//	printf("%d %d %d %d 3 rt %d\n", ds->op, ds->a, ds->b, ds->c, pr_opcodes[ds->op].type_c->type->type);
1713 			type[8] = pr_opcodes[ds->op].type_c->type->type;
1714 			if (type[8] == ev_pointer)
1715 				type[8] = BackBuildReturnType(dft, ds, ds->c);
1716 			break;
1717 		}
1718 	}
1719 
1720 	/* find name */
1721 	memset (sname, 0, sizeof(sname));
1722 	arg1 = PR_PrintStringAtOfs(dsf->a, 0);
1723 	sprintf(sname, "%s", arg1);
1724 
1725 	/* look for first two parms */
1726 	if (dsf->b == 1)
1727 		type[0] = GetLastFunctionReturn(dft, dsf);
1728 	else	type[0] = GetType(dsf->b);
1729 
1730 	if (type[0] == ev_pointer)
1731 		type[0] = BackBuildReturnType(dft, dsf, dsf->b);
1732 
1733 	if (dsf->c == 1)
1734 		type[1] = GetLastFunctionReturn(dft, dsf);
1735 	else	type[1] = GetType(dsf->c);
1736 
1737 	printf("type b %d %d\n", type[0], (progs->version == PROG_VERSION_V6) ? (signed short)dsf->b : dsf->b);
1738 	printf("type c %d %d\n", type[1], (progs->version == PROG_VERSION_V6) ? (signed short)dsf->c : dsf->c);
1739 	if (type[1] == ev_pointer)
1740 		type[1] = BackBuildReturnType(dft, dsf, dsf->c);
1741 
1742 	/* look in regs for rest of parms */
1743 	i = 2;
1744 
1745 	while (i < j)
1746 	{
1747 		if (i > 8)	/* just in case.. */
1748 			COM_Error ("%s (%d): array out of bounds.", __thisfunc__, __LINE__);
1749 		type[i] = ev_void;
1750 		for (ds = dsf; ds - pr_statements >= dft->first_statement; ds--)
1751 		{
1752 			if (ds->a == ((3 * i) + 4))
1753 			{
1754 			//	printf("a ");
1755 				type[i] = GetType(ds->a);
1756 				if (type[i] == ev_pointer)
1757 					type[i] = BackBuildReturnType(dft, ds, ds->a);
1758 				break;
1759 			}
1760 
1761 			if (ds->b == ((3 * i) + 4))
1762 			{
1763 			//	printf("b ");
1764 				if (pr_opcodes[ds->op].right_associative)
1765 				{
1766 					type[i] = GetType(ds->a);
1767 					if (type[i] == ev_pointer || type[i] == ev_field)
1768 						type[i] = BackBuildReturnType(dft, ds, ds->a);
1769 				}
1770 				else
1771 				{
1772 					type[i] = GetType(ds->c);
1773 					if (type[i] == ev_pointer || type[i] == ev_field)
1774 						type[i] = BackBuildReturnType(dft, ds, ds->c);
1775 				}
1776 				break;
1777 			}
1778 
1779 			if (ds->c == ((3 * i) + 4))
1780 			{
1781 			//	printf("c ");
1782 				type[i] = GetType(ds->a);
1783 				if (type[i] == ev_pointer)
1784 					type[i] = BackBuildReturnType(dft, ds, ds->c);
1785 				break;
1786 			}
1787 		}
1788 
1789 	//	printf("type %i: op: %d a:%d b: %d c: %d rt: %d\n", i, ds->op, ds->a, ds->b, ds->c, type[i]);
1790 		i++;
1791 	}
1792 
1793 	/* print results to string */
1794 	memset (plist, 0, sizeof(plist));
1795 	if (type[8] & DEF_SAVEGLOBAL)
1796 	{
1797 		sprintf(plist,".");
1798 		type[8] &= ~DEF_SAVEGLOBAL;
1799 	}
1800 
1801 	switch (type[8])
1802 	{
1803 	case ev_string:
1804 		strcat(plist, "string ");
1805 		break;
1806 	case ev_void:
1807 		strcat(plist, "void ");
1808 		break;
1809 	case ev_float:
1810 		strcat(plist, "float ");
1811 		break;
1812 	case ev_vector:
1813 		strcat(plist, "vector ");
1814 		break;
1815 	case ev_entity:
1816 		strcat(plist, "entity ");
1817 		break;
1818 	case ev_field:
1819 		strcat(plist, "ev_field ");
1820 		break;
1821 	case ev_function:
1822 		strcat(plist, "void() ");
1823 		break;
1824 	case ev_pointer:
1825 		strcat(plist, "ev_pointer ");
1826 		break;
1827 	default:
1828 		strcat(plist, "unknown ");
1829 		break;
1830 	}
1831 
1832 	strcat(plist, "(");
1833 	if (df->numparms < 0)
1834 	{
1835 		strcat(plist, "...");
1836 	}
1837 	else
1838 	{
1839 		for (i = 0; i < j; i++)
1840 		{
1841 			if (type[i] & DEF_SAVEGLOBAL)
1842 			{
1843 				strcat(plist, ".");
1844 				type[i] &= ~DEF_SAVEGLOBAL;
1845 			}
1846 
1847 			switch (type[i])
1848 			{
1849 			case ev_string:
1850 				strcat(plist, "string ");
1851 				break;
1852 			case ev_void:
1853 				strcat(plist, "void ");
1854 				break;
1855 			case ev_float:
1856 				strcat(plist, "float ");
1857 				break;
1858 			case ev_vector:
1859 				strcat(plist, "vector ");
1860 				break;
1861 			case ev_entity:
1862 				strcat(plist, "entity ");
1863 				break;
1864 			case ev_field:
1865 				strcat(plist, "ev_field ");
1866 				break;
1867 			case ev_function:
1868 				strcat(plist, "void() ");
1869 				break;
1870 			case ev_pointer:
1871 				strcat(plist, "ev_pointer ");
1872 				break;
1873 			default:
1874 				sprintf(parm, "unknown%d",type[i]);
1875 				strcat(plist, parm);
1876 				break;
1877 			}
1878 
1879 			sprintf(parm, "%c", 'a'+i);
1880 			strcat(plist, parm);
1881 
1882 			if (i < j - 1)
1883 				strcat(plist, ", ");
1884 		}
1885 	}
1886 
1887 	strcat(plist, ")");
1888 	func_headers[func] = SafeStrdup(plist);
1889 	printf("%s%s\nin %s in file %s\n", plist, sname, pr_strings + dft->s_name, pr_strings + dft->s_file);
1890 }
1891 
1892 
BackBuildReturnType(dfunction_t * df,dstatement_t * dsf,gofs_t ofs)1893 static unsigned short BackBuildReturnType (dfunction_t *df,dstatement_t *dsf, gofs_t ofs)
1894 {
1895 	dstatement_t	*ds;
1896 	unsigned short	rtype = ev_void;
1897 	ddef_t		*par;
1898 
1899 //	printf("backbuilding...\n");
1900 
1901 	for (ds = dsf - 1; ds - pr_statements >= df->first_statement; ds--)
1902 	{
1903 		if (ds->a == ofs)
1904 		{
1905 			rtype = pr_opcodes[ds->op].type_a->type->type;
1906 			par = DEC_GetParameter (ds->b);
1907 			if (par)
1908 			{
1909 			//	printf("ds->b type: %d\n", par->type);
1910 				rtype = par->type;
1911 			}
1912 			break;
1913 		}
1914 
1915 		if (ds->b == ofs)
1916 		{
1917 			rtype = pr_opcodes[ds->op].type_b->type->type;
1918 			par = DEC_GetParameter (ds->a);
1919 			if (par)
1920 			{
1921 			//	printf("ds->a type: %d\n", par->type);
1922 				rtype = par->type;
1923 			}
1924 			break;
1925 		}
1926 
1927 		if (ds->c == ofs)
1928 		{
1929 			rtype = pr_opcodes[ds->op].type_c->type->type;
1930 		//	rtype = GetType(ds->b);
1931 			break;
1932 		}
1933 	}
1934 
1935 	return rtype;
1936 }
1937 
1938 
GetType(gofs_t ofs)1939 static unsigned short GetType (gofs_t ofs)
1940 {
1941 	ddef_t		*par;
1942 	unsigned short	rtype;
1943 	ddef_t		*ef;
1944 
1945 	rtype = ev_pointer;
1946 	par = DEC_GetParameter (ofs);
1947 
1948 	if (par)
1949 	{
1950 		par->type &= ~DEF_SAVEGLOBAL;
1951 
1952 		if (par->type == ev_field)
1953 		{
1954 			ef = PR_GetField(pr_strings + par->s_name, par);
1955 			if (!ef)
1956 				COM_Error("Could not locate a field named \"%s\"", pr_strings + par->s_name);
1957 			rtype = (ef->type | DEF_SAVEGLOBAL);
1958 		}
1959 		else
1960 		{
1961 			rtype = par->type;
1962 		}
1963 	}
1964 
1965 	return rtype;
1966 }
1967 
1968 
DccFunctionOP(unsigned short op)1969 static void DccFunctionOP (unsigned short op)
1970 {
1971 	int		i, j = 0;
1972 	dfunction_t	*df;
1973 	dstatement_t	*ds;
1974 
1975 	for (i = 1; i < progs->numfunctions; i++)
1976 	{
1977 		df = pr_functions + i;
1978 
1979 		if (df->first_statement < 0)
1980 			continue;
1981 
1982 		for (ds = &pr_statements[df->first_statement]; ds && ds->op; ds++)
1983 		{
1984 			if (ds->op == op && j++)
1985 			{
1986 				PR_PrintFunction(pr_strings + df->s_name);
1987 				return;
1988 			}
1989 		}
1990 	}
1991 }
1992 
1993 
1994 /*
1995 ===============
1996 DEC_ConvertV6Defs, DEC_ConvertV6Stmts -- Pa3PyX
1997 
1998 Convert ddef_v6_t and dstatement_v6_t arrays into _v7 format
1999 with byte swapping.
2000 ===============
2001 */
DEC_ConvertV6Defs(ddef_v6_t * v6defs,int numdefs)2002 static ddef_v7_t *DEC_ConvertV6Defs (ddef_v6_t *v6defs, int numdefs)
2003 {
2004 	int		i;
2005 	ddef_v7_t	*v7defs, *v7ptr;
2006 	ddef_v6_t	*v6ptr;
2007 
2008 	v7defs = (ddef_v7_t *) SafeMalloc(sizeof(ddef_v7_t) * numdefs);
2009 	for (i = 0, v6ptr = v6defs, v7ptr = v7defs; i < numdefs; i++, v6ptr++, v7ptr++)
2010 	{
2011 		v7ptr->type = LittleShort(v6ptr->type);
2012 		v7ptr->ofs = (unsigned short)LittleShort(v6ptr->ofs);
2013 		v7ptr->s_name = LittleLong(v6ptr->s_name);
2014 	}
2015 
2016 	return v7defs;
2017 }
2018 
DEC_ConvertV6Stmts(dstatement_v6_t * v6stmts,int numstmts)2019 static dstatement_v7_t *DEC_ConvertV6Stmts (dstatement_v6_t *v6stmts, int numstmts)
2020 {
2021 	int		i;
2022 	dstatement_v7_t	*v7stmts, *v7ptr;
2023 	dstatement_v6_t	*v6ptr;
2024 
2025 	v7stmts = (dstatement_v7_t *) SafeMalloc(sizeof(dstatement_v7_t) * numstmts);
2026 	for (i = 0, v6ptr = v6stmts, v7ptr = v7stmts; i < numstmts; i++, v6ptr++, v7ptr++)
2027 	{
2028 		v7ptr->op = LittleShort(v6ptr->op);
2029 		v7ptr->a = (unsigned short)LittleShort(v6ptr->a);
2030 		v7ptr->b = (unsigned short)LittleShort(v6ptr->b);
2031 		v7ptr->c = (unsigned short)LittleShort(v6ptr->c);
2032 	}
2033 
2034 	return v7stmts;
2035 }
2036 
DEC_ReadData(const char * srcfile)2037 static void DEC_ReadData (const char *srcfile)
2038 {
2039 	void		*p;
2040 	int		i;
2041 
2042 	progs_length = LoadFile (srcfile, &p);
2043 	progs = (dprograms_t *) p;
2044 
2045 	/* byte swap the header */
2046 	for (i = 0; i < (int) sizeof(*progs) / 4; i++)
2047 		((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
2048 
2049 	printf ("read data from %s:\n", srcfile);
2050 	printf ("%10i bytes, version %i, crc: %i\n", progs_length, progs->version, progs->crc);
2051 	printf ("%10i strofs\n", progs->numstrings);
2052 	printf ("%10i numstatements\n", progs->numstatements);
2053 	printf ("%10i numfunctions\n", progs->numfunctions);
2054 	printf ("%10i numglobaldefs\n", progs->numglobaldefs);
2055 	printf ("%10i numfielddefs\n", progs->numfielddefs);
2056 	printf ("%10i numpr_globals\n", progs->numglobals);
2057 	printf ("----------------------------------------\n");
2058 
2059 	if (pr_infoonly != 0)
2060 		return;
2061 
2062 	switch (progs->version)
2063 	{
2064 	case PROG_VERSION_V6:
2065 	case PROG_VERSION_V7:
2066 		break;
2067 	default:
2068 		COM_Error("%s is of unsupported version (%d, should be %d or %d)",
2069 			  srcfile, progs->version, PROG_VERSION_V6, PROG_VERSION_V7);
2070 		break;
2071 	}
2072 
2073 	pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
2074 	pr_globals = (float *)((byte *)progs + progs->ofs_globals);
2075 	pr_strings = (char *)progs + progs->ofs_strings;
2076 
2077 	if (progs->version == PROG_VERSION_V6)
2078 	{
2079 		pr_globaldefs = DEC_ConvertV6Defs ((ddef_v6_t *)((byte *)progs + progs->ofs_globaldefs), progs->numglobaldefs);
2080 		pr_fielddefs  = DEC_ConvertV6Defs ((ddef_v6_t *)((byte *)progs + progs->ofs_fielddefs),  progs->numfielddefs);
2081 		pr_statements = DEC_ConvertV6Stmts((dstatement_v6_t *)((byte *)progs + progs->ofs_statements), progs->numstatements);
2082 	}
2083 	else
2084 	{
2085 		pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
2086 		pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
2087 		pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
2088 	}
2089 
2090 	/* byte swap the lumps */
2091 	for (i = 0; i < progs->numfunctions; i++)
2092 	{
2093 		pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
2094 		pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
2095 		pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
2096 		pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
2097 		pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
2098 		pr_functions[i].locals = LittleLong (pr_functions[i].locals);
2099 	}
2100 
2101 	if (progs->version == PROG_VERSION_V7)
2102 	{
2103 		for (i = 0; i < progs->numstatements; i++)
2104 		{
2105 			pr_statements[i].op = LittleShort(pr_statements[i].op);
2106 			pr_statements[i].a = LittleLong(pr_statements[i].a);
2107 			pr_statements[i].b = LittleLong(pr_statements[i].b);
2108 			pr_statements[i].c = LittleLong(pr_statements[i].c);
2109 		}
2110 
2111 		for (i = 0; i < progs->numglobaldefs; i++)
2112 		{
2113 			pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
2114 			pr_globaldefs[i].ofs = LittleLong (pr_globaldefs[i].ofs);
2115 			pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
2116 		}
2117 
2118 		for (i = 0; i < progs->numfielddefs; i++)
2119 		{
2120 			pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
2121 			pr_fielddefs[i].ofs = LittleLong (pr_fielddefs[i].ofs);
2122 			pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
2123 		}
2124 	}
2125 
2126 	for (i = 0; i < progs->numglobals; i++)
2127 		((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
2128 }
2129 
2130 
Init_Dcc(void)2131 static void Init_Dcc (void)
2132 {
2133 	int		i;
2134 
2135 	def_ret.ofs = OFS_RETURN;
2136 	for (i = 0; i < MAX_PARMS; i++)
2137 		def_parms[i].ofs = OFS_PARM0 + 3*i;
2138 
2139 	if (CheckParm("-fix"))		/* fix mangled names */
2140 		FILE_NUM_FOR_NAME = true;
2141 	else	FILE_NUM_FOR_NAME = false;
2142 
2143 	if (CheckParm("-dump"))
2144 		pr_dumpasm = true;
2145 	else	pr_dumpasm = false;
2146 
2147 	PR_FILE = stdout;
2148 	cfunc = NULL;
2149 	printassign = false;
2150 
2151 	DEC_FileCtr = 0;
2152 
2153 	func_headers = (char **) SafeMalloc (progs->numfunctions * sizeof(char *));
2154 	temp_val = (char **) SafeMalloc (progs->numglobals * sizeof(char *));
2155 	DEC_FilesSeen = (char **) SafeMalloc (MAX_DEC_FILES * sizeof(char *));
2156 	flowinfo = (struct flowinfo_t *) SafeMalloc (progs->numstatements * sizeof(struct flowinfo_t));
2157 }
2158 
2159 
DEC_GetFunctionIdxByName(const char * name)2160 static int DEC_GetFunctionIdxByName (const char *name)
2161 {
2162 	int	i;
2163 
2164 	for (i = 1; i < progs->numfunctions; i++)
2165 	{
2166 		if (!strcmp (name, pr_strings + pr_functions[i].s_name))
2167 			return i;
2168 	}
2169 
2170 	return 0;
2171 }
2172 
2173 
DEC_GetParameter(gofs_t ofs)2174 static ddef_t *DEC_GetParameter (gofs_t ofs)
2175 {
2176 	int		i;
2177 	ddef_t		*def;
2178 
2179 	def = NULL;
2180 
2181 	for (i = 0; i < progs->numglobaldefs; i++)
2182 	{
2183 		def = &pr_globaldefs[i];
2184 		if (def->ofs == ofs)
2185 			return def;
2186 	}
2187 
2188 	return NULL;
2189 }
2190 
2191 
DEC_AlreadySeen(const char * fname)2192 static int DEC_AlreadySeen (const char *fname)
2193 {
2194 	int		i;
2195 	char		*new1;
2196 
2197 	for (i = 0; i < DEC_FileCtr; i++)
2198 	{
2199 		if (!strcmp(fname, DEC_FilesSeen[i]))
2200 			return 1;
2201 	}
2202 
2203 	if (DEC_FileCtr >= MAX_DEC_FILES - 1)
2204 		COM_Error("%s: too many source files.", __thisfunc__);
2205 
2206 	new1 = SafeStrdup(fname);
2207 	DEC_FilesSeen[DEC_FileCtr++] = new1;
2208 
2209 	return 0;
2210 }
2211 
2212 
2213 #if 0	/* not used */
2214 static void FixFunctionNames (void)
2215 {
2216 	int		i, j;
2217 	dfunction_t	*d;
2218 	char	s[128], *c;
2219 
2220 	for (i = 1; i < progs->numfunctions; i++)
2221 	{
2222 		d = &pr_functions[i];
2223 	//	printf ("%s : %s : %i %i (", pr_strings + d->s_file, pr_strings + d->s_name, d->first_statement, d->parm_start);
2224 		s[0] = '\0';
2225 		j = strlen(pr_strings + d->s_file) + 1;
2226 		sprintf (s, "%d.hc", d->s_file);
2227 		c = pr_strings;
2228 		c += d->s_file;
2229 		sprintf (c, "%s", s);
2230 	}
2231 }
2232 #endif	/* end of unused */
2233 
2234 
PR_String(const char * string)2235 static const char *PR_String (const char *string)
2236 {
2237 	static char	buf[80];
2238 	char	*s;
2239 
2240 	s = buf;
2241 	*s++ = '"';
2242 	while (string && *string)
2243 	{
2244 		if (s == buf + sizeof(buf) - 2)
2245 			break;
2246 		if (*string == '\n')
2247 		{
2248 			*s++ = '\\';
2249 			*s++ = 'n';
2250 		}
2251 		else if (*string == '"')
2252 		{
2253 			*s++ = '\\';
2254 			*s++ = '"';
2255 		}
2256 		else
2257 			*s++ = *string;
2258 		string++;
2259 		if (s - buf > 60)
2260 		{
2261 			*s++ = '.';
2262 			*s++ = '.';
2263 			*s++ = '.';
2264 			break;
2265 		}
2266 	}
2267 	*s++ = '"';
2268 	*s++ = 0;
2269 	return buf;
2270 }
2271 
PR_DefForFieldOfs(gofs_t ofs)2272 static def_t *PR_DefForFieldOfs (gofs_t ofs)
2273 {
2274 	def_t	*d;
2275 
2276 	for (d = pr.def_head.next; d; d = d->next)
2277 	{
2278 		if (d->type->type != ev_field)
2279 			continue;
2280 		if (((int *)pr_globals)[d->ofs] == ofs)
2281 			return d;
2282 	}
2283 	COM_Error ("%s: couldn't find %i", __thisfunc__, ofs);
2284 	return NULL;
2285 }
2286 
PR_ValueString(etype_t type,void * val)2287 static const char *PR_ValueString (etype_t type, void *val)
2288 {
2289 	static char	line[256];
2290 	def_t		*def;
2291 	dfunction_t	*f;
2292 
2293 	switch (type)
2294 	{
2295 	case ev_string:
2296 		sprintf (line, "%s", PR_String(pr_strings + *(int *)val));
2297 		break;
2298 	case ev_entity:
2299 		sprintf (line, "entity %i", *(int *)val);
2300 		break;
2301 	case ev_function:
2302 		f = pr_functions + *(int *)val;
2303 		if (!f)
2304 			sprintf (line, "undefined function");
2305 		else
2306 			sprintf (line, "%s()", pr_strings + f->s_name);
2307 		break;
2308 	case ev_field:
2309 		def = PR_DefForFieldOfs ( *(int *)val );
2310 		sprintf (line, ".%s", def->name);
2311 		break;
2312 	case ev_void:
2313 		sprintf (line, "void");
2314 		break;
2315 	case ev_float:
2316 		sprintf (line, "%5.1f", *(float *)val);
2317 		break;
2318 	case ev_vector:
2319 		sprintf (line, "'%5.1f %5.1f %5.1f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
2320 		break;
2321 	case ev_pointer:
2322 		sprintf (line, "pointer");
2323 		break;
2324 	default:
2325 		sprintf (line, "bad type %i", type);
2326 		break;
2327 	}
2328 
2329 	return line;
2330 }
2331 
DCC_ValueString(etype_t type,void * val)2332 static const char *DCC_ValueString (etype_t type, void *val)
2333 {
2334 	static char	vsline[256];
2335 	def_t		*def;
2336 	dfunction_t	*f;
2337 
2338 	switch (type)
2339 	{
2340 	case ev_string:
2341 		sprintf (vsline, "%s", PR_String(pr_strings + *(int *)val));
2342 		break;
2343 	case ev_entity:
2344 		sprintf (vsline, "entity %i", *(int *)val);
2345 		break;
2346 	case ev_function:
2347 		f = pr_functions + *(int *)val;
2348 		if (!f)
2349 			sprintf (vsline, "undefined function");
2350 		else	sprintf (vsline, "%s()", pr_strings + f->s_name);
2351 		break;
2352 	case ev_field:
2353 		def = PR_DefForFieldOfs (*(int *)val);
2354 		sprintf (vsline, ".%s", def->name);
2355 		break;
2356 	case ev_void:
2357 		sprintf (vsline, "void");
2358 		break;
2359 	case ev_float:
2360 		sprintf (vsline, "%.5f", *(float *)val);
2361 		break;
2362 	case ev_vector:
2363 		sprintf (vsline, "'%.5f %.5f %.5f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
2364 		break;
2365 	case ev_pointer:
2366 		sprintf (vsline, "pointer");
2367 		break;
2368 	default:
2369 		sprintf (vsline, "bad type %i", type);
2370 		break;
2371 	}
2372 
2373 	return vsline;
2374 }
2375 
2376 
PR_PrintFunction(const char * name)2377 static void PR_PrintFunction (const char *name)
2378 {
2379 	int		i;
2380 	dstatement_t	*ds;
2381 	dfunction_t	*df;
2382 	const char	*arg1, *arg2;
2383 	def_t		*typ1, *typ2;
2384 
2385 	for (i = 0; i < progs->numfunctions; i++)
2386 	{
2387 		if (!strcmp (name, pr_strings + pr_functions[i].s_name))
2388 			break;
2389 	}
2390 
2391 	if (i == progs->numfunctions)
2392 		COM_Error ("No function names \"%s\"", name);
2393 
2394 	df = pr_functions + i;
2395 	cfunc = df;
2396 	printf("Statements for %s:\n", name);
2397 	ds = pr_statements + df->first_statement;
2398 	Clear_Immediates();
2399 	PR_LocalGlobals();
2400 	PR_FunctionHeader(df);
2401 
2402 	if (df->first_statement < 0)
2403 	{
2404 		PR_Print("\n%s%s = #%d;\n", func_headers[df - pr_functions], pr_strings + df->s_name, -df->first_statement);
2405 		return;
2406 	}
2407 
2408 	PR_Print("\n%s%s = ", func_headers[df - pr_functions], pr_strings + df->s_name);
2409 
2410 	if (ds->op == OP_STATE)
2411 	{
2412 		typ1 = pr_opcodes[ds->op].type_a;
2413 		typ2 = pr_opcodes[ds->op].type_b;
2414 		arg1 = PR_ValueString(typ1->type->type, &pr_globals[ds->a]);
2415 		arg2 = PR_PrintStringAtOfs(ds->b, typ2);
2416 		PR_Print(" [%s, %s]", arg1, arg2);
2417 	}
2418 
2419 	PR_Print(" {\n");
2420 	AddProgramFlowInfo(df);
2421 	PR_Locals(df);
2422 	lindent = 1;
2423 
2424 	while (1)
2425 	{
2426 		DccStatement(ds);
2427 		if (!ds->op)
2428 			break;
2429 		ds++;
2430 	}
2431 }
2432 
2433 
GetLastFunctionReturn(dfunction_t * df,dstatement_t * ds)2434 static unsigned short GetLastFunctionReturn (dfunction_t *df, dstatement_t *ds)
2435 {
2436 	dstatement_t	*di;
2437 	int		i;
2438 	const char	*arg1;
2439 	def_t		*type1;
2440 
2441 	printf("looking for last return type\n");
2442 
2443 	di = ds - 1;
2444 
2445 	while ((di - pr_statements) >= df->first_statement)
2446 	{	/* that stupid equal, what a bitch */
2447 		printf(" op %d a: %d b: %d c: %d\n", di->op, di->a, di->b, di->c);
2448 
2449 		if (OP_CALL0 <= di->op && di->op <= OP_CALL8)
2450 		{
2451 			type1 = pr_opcodes[di->op].type_a;
2452 			arg1 = PR_PrintStringAtOfs(di->a, type1);
2453 			if (!arg1)
2454 				COM_Error("function name not found!!!\n");
2455 
2456 			i = DEC_GetFunctionIdxByName(arg1);
2457 			if (i == 0)
2458 				break;
2459 
2460 			if (i != (df - pr_functions))
2461 			{
2462 				i = GetReturnType(i);
2463 				printf("%s %d is found\n", arg1, i);
2464 				return i;
2465 			}
2466 			else
2467 			{
2468 				break;
2469 			}
2470 		} /* end if call */
2471 		else if (OP_RAND0 <= di->op && di->op <= OP_RAND2)
2472 		{
2473 			return ev_float;
2474 		}
2475 		else if (OP_RANDV0 <= di->op && di->op <= OP_RANDV2)
2476 		{
2477 			return ev_vector;
2478 		}
2479 
2480 		di--;
2481 	} /* end while ofs_return */
2482 
2483 	return ev_void;
2484 }
2485 
PrintGlobaldefs(void)2486 static void PrintGlobaldefs (void)
2487 {
2488 	int		i;
2489 	ddef_t		*d;
2490 
2491 	for (i = 0; i < progs->numglobaldefs; i++)
2492 	{
2493 		d = &pr_globaldefs[i];
2494 		printf ("%5i : (%i) %s\n", d->ofs, d->type, pr_strings + d->s_name);
2495 	}
2496 }
2497 
PrintPRGlobals(void)2498 static void PrintPRGlobals (void)
2499 {
2500 	int		i;
2501 
2502 	for (i = 0; i < progs->numglobals; i++)
2503 	{
2504 		printf ("%5i %5.5f %5d\n", i, pr_globals[i], ((int *)pr_globals)[i]);
2505 	}
2506 }
2507 
PrintStatements(void)2508 static void PrintStatements (void)
2509 {
2510 	int		i;
2511 	dstatement_t	*ds;
2512 
2513 	for (i = 0; i < progs->numstatements; i++)
2514 	{
2515 		ds = pr_statements + i;
2516 		printf ("%5d op: %2d a: %5d b: %5d c: %5d\n", i, ds->op, ds->a, ds->b, ds->c);
2517 	}
2518 }
2519 
PrintStrings(void)2520 static void PrintStrings (void)
2521 {
2522 	int		i, l;
2523 	const char	*s;
2524 
2525 	for (i = 0; i < progs->numstrings; i += l)
2526 	{
2527 		s = pr_strings + i;
2528 		l = strlen(s) + 1;
2529 		printf ("%5i : ", i);
2530 		for ( ; *s; ++s)
2531 		{
2532 			if (*s == '\n')
2533 			{
2534 				putchar ('\\');
2535 				putchar ('n');
2536 			}
2537 			else
2538 				putchar (*s);
2539 		}
2540 		printf ("\n");
2541 	}
2542 }
2543 
PrintFunctions(void)2544 static void PrintFunctions (void)
2545 {
2546 	int		i, j;
2547 	dfunction_t	*d;
2548 
2549 	for (i = 0; i < progs->numfunctions; i++)
2550 	{
2551 		d = &pr_functions[i];
2552 		printf ("%s : %s : %i %i (", pr_strings + d->s_file, pr_strings + d->s_name, d->first_statement, d->parm_start);
2553 		for (j = 0; j < d->numparms; j++)
2554 			printf ("%i ", d->parm_size[j]);
2555 		printf (")\n");
2556 	}
2557 }
2558 
PrintFields(void)2559 static void PrintFields (void)
2560 {
2561 	int		i;
2562 	ddef_t		*d;
2563 
2564 	for (i = 0; i < progs->numfielddefs; i++)
2565 	{
2566 		d = &pr_fielddefs[i];
2567 		printf ("%5i %5i : (%i) %s\n", i, d->ofs, d->type, pr_strings + d->s_name);
2568 	}
2569 }
2570 
Dcc_main(int argc,char ** argv)2571 int Dcc_main (int argc, char **argv)
2572 {
2573 	int		p;
2574 	double	start, stop;
2575 
2576 	start = COM_GetTime ();
2577 
2578 	pr_infoonly = CheckParm("-info");
2579 
2580 	p = CheckParm("-name");
2581 	if (p == 0)
2582 		DEC_ReadData ("progs.dat");
2583 	else
2584 	{
2585 		if (p >= argc - 1)
2586 			COM_Error ("No input filename specified with -name");
2587 		DEC_ReadData (argv[p + 1]);
2588 	}
2589 
2590 	if (pr_infoonly != 0)
2591 		return 0;
2592 
2593 	/* don't need Init_Dcc () for the following info stuff */
2594 	if (CheckParm("-fields") != 0)
2595 	{
2596 		printf("\nFIELDS =========================\n");
2597 		PrintFields ();
2598 		return 0;
2599 	}
2600 	if (CheckParm("-functions") != 0)
2601 	{
2602 		printf("\nFUNCTIONS ======================\n");
2603 		PrintFunctions ();
2604 		return 0;
2605 	}
2606 	if (CheckParm("-globaldefs") != 0)
2607 	{
2608 		printf("\nGLOBALDEFS =====================\n");
2609 		PrintGlobaldefs();
2610 		return 0;
2611 	}
2612 	if (CheckParm("-prglobals") != 0)
2613 	{
2614 		printf("\nPR_GLOBALS =====================\n");
2615 		PrintPRGlobals ();
2616 		return 0;
2617 	}
2618 	if (CheckParm("-statements") != 0)
2619 	{
2620 		printf("\nSTATEMENTS =====================\n");
2621 		PrintStatements();
2622 		return 0;
2623 	}
2624 	if (CheckParm("-strings") != 0)
2625 	{
2626 		printf("\nSTRINGS ========================\n");
2627 		PrintStrings ();
2628 		return 0;
2629 	}
2630 
2631 	Init_Dcc ();
2632 
2633 	p = CheckParm("-bbb");
2634 	if (p != 0)
2635 	{
2636 		/*
2637 		i= -999;
2638 		for (p = 0; p < progs->numstatements; ++p)
2639 		{
2640 			if ((pr_statements + p)->op > i)
2641 				i = (pr_statements + p)->op;
2642 		}
2643 		printf("largest op %d\n", i);
2644 		*/
2645 		FindBuiltinParameters(1);
2646 		return 0;
2647 	}
2648 
2649 	p = CheckParm("-ddd");
2650 	if (p != 0)
2651 	{
2652 		for (++p; p < argc; ++p)
2653 		{
2654 			if (argv[p][0] == '-')
2655 				break;
2656 			DccFunctionOP (atoi(argv[p]));
2657 		}
2658 		return 0;
2659 	}
2660 
2661 	p = CheckParm("-asm");
2662 	if (p != 0)
2663 	{
2664 		for (++p; p < argc; ++p)
2665 		{
2666 			if (argv[p][0] == '-')
2667 				break;
2668 			PR_PrintFunction(argv[p]);
2669 		}
2670 	}
2671 	else
2672 	{
2673 		Dcc_Functions ();
2674 		stop = COM_GetTime ();
2675 		printf("\n%d seconds elapsed.\n", (int)(stop - start));
2676 	}
2677 
2678 	return 0;
2679 }
2680 
2681