From 9cccb7a4d42138fc44e03426c28629b72a6bdfff Mon Sep 17 00:00:00 2001
From: Bill Currie <bill@taniwha.org>
Date: Fri, 29 Apr 2022 15:38:55 +0900
Subject: [PATCH] [qfcc] Implement ulong, long and uint constants

Finally :P
---
 tools/qfcc/include/expr.h    |  3 +++
 tools/qfcc/include/value.h   |  2 ++
 tools/qfcc/source/expr.c     | 12 ++++++++++++
 tools/qfcc/source/qc-lex.l   | 18 +++++++++++++-----
 tools/qfcc/source/qc-parse.y | 10 ++++++----
 tools/qfcc/source/value.c    | 16 ++++++++++++++++
 6 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h
index 5635141f2..0f460445d 100644
--- a/tools/qfcc/include/expr.h
+++ b/tools/qfcc/include/expr.h
@@ -633,6 +633,9 @@ int expr_int (expr_t *e) __attribute__((pure));
 expr_t *new_uint_expr (unsigned uint_val);
 unsigned expr_uint (expr_t *e) __attribute__((pure));
 
+expr_t *new_long_expr (pr_long_t long_val);
+expr_t *new_ulong_expr (pr_ulong_t ulong_val);
+
 /** Create a new short constant expression node.
 
 	\param short_val	The short constant being represented.
diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h
index 197c31514..e8eb5a3a7 100644
--- a/tools/qfcc/include/value.h
+++ b/tools/qfcc/include/value.h
@@ -56,6 +56,8 @@ struct ex_value_s *new_pointer_val (int val, struct type_s *type,
 struct ex_value_s *new_quaternion_val (const float *quaternion_val);
 struct ex_value_s *new_int_val (int int_val);
 struct ex_value_s *new_uint_val (int uint_val);
+struct ex_value_s *new_long_val (pr_long_t long_val);
+struct ex_value_s *new_ulong_val (pr_ulong_t ulong_val);
 struct ex_value_s *new_short_val (short short_val);
 struct ex_value_s *new_nil_val (struct type_s *type);
 struct ex_value_s *new_type_value (const struct type_s *type,
diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c
index fe6a10dd3..daea88014 100644
--- a/tools/qfcc/source/expr.c
+++ b/tools/qfcc/source/expr.c
@@ -752,6 +752,18 @@ new_uint_expr (unsigned uint_val)
 	return new_value_expr (new_uint_val (uint_val));
 }
 
+expr_t *
+new_long_expr (pr_long_t long_val)
+{
+	return new_value_expr (new_long_val (long_val));
+}
+
+expr_t *
+new_ulong_expr (pr_ulong_t ulong_val)
+{
+	return new_value_expr (new_ulong_val (ulong_val));
+}
+
 expr_t *
 new_short_expr (short short_val)
 {
diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l
index ee63d6791..495d69aa9 100644
--- a/tools/qfcc/source/qc-lex.l
+++ b/tools/qfcc/source/qc-lex.l
@@ -131,17 +131,25 @@ STRING		\"(\\.|[^"\\])*\"
 
 {INT}+{UL}?			{
 						const char *c = yytext + yyleng - 1;
-						int         i;
+						pr_long_t   i;
 
 						if (yytext[0] == '0' && tolower (yytext[1] == 'b'))
 							i = strtol (yytext + 2, 0, 2);
 						else
 							i = strtol (yytext, 0, 0);
-						if (*c == 'u' || *c == 'U') {
-							qc_yylval.expr = new_int_expr (i);//FIXME
+						if (tolower (*c) == 'u') {
+							if (tolower (c[1]) == 'l') {
+								qc_yylval.expr = new_ulong_expr (i);
+							} else {
+								qc_yylval.expr = new_uint_expr (i);
+							}
 						} else {
-							qc_yylval.expr = new_int_expr (i);
-							qc_yylval.expr->implicit = 1;
+							if (tolower (c[1]) == 'l') {
+								qc_yylval.expr = new_long_expr (i);
+							} else {
+								qc_yylval.expr = new_int_expr (i);
+								qc_yylval.expr->implicit = 1;
+							}
 						}
 						return VALUE;
 					}
diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y
index 29029e543..5355a7981 100644
--- a/tools/qfcc/source/qc-parse.y
+++ b/tools/qfcc/source/qc-parse.y
@@ -94,7 +94,7 @@ int yylex (void);
 
 %union {
 	int			op;
-	int         size;
+	unsigned    size;
 	specifier_t spec;
 	void       *pointer;			// for ensuring pointer values are null
 	struct type_s	*type;
@@ -1131,11 +1131,13 @@ abs_decl
 array_decl
 	: '[' expr ']'
 		{
-			if (!is_int_val ($2) || expr_int ($2) < 1) {
+			if (is_int_val ($2) && expr_int ($2) > 0) {
+				$$ = expr_int ($2);
+			} else if (is_uint_val ($2) && expr_uint ($2) > 0) {
+				$$ = expr_uint ($2);
+			} else {
 				error (0, "invalid array size");
 				$$ = 0;
-			} else {
-				$$ = expr_int ($2);
 			}
 		}
 	| '[' ']'					{ $$ = 0; }
diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c
index 8661a140b..bd8ac599e 100644
--- a/tools/qfcc/source/value.c
+++ b/tools/qfcc/source/value.c
@@ -240,6 +240,22 @@ new_uint_val (int uint_val)
 	return find_value (&val);
 }
 
+ex_value_t *
+new_long_val (pr_long_t long_val)
+{
+	ex_value_t  val = { .v = { .long_val = long_val } };
+	set_val_type (&val, &type_long);
+	return find_value (&val);
+}
+
+ex_value_t *
+new_ulong_val (pr_ulong_t ulong_val)
+{
+	ex_value_t  val = { .v = { .ulong_val = ulong_val } };
+	set_val_type (&val, &type_ulong);
+	return find_value (&val);
+}
+
 ex_value_t *
 new_short_val (short short_val)
 {