From 428d2b3ef8d672cd38beebf84d9f0d67f98ed3c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonathan=20Sch=C3=B6bel?= <jonathan@xn--schbel-yxa.info>
Date: Mon, 1 Apr 2024 14:01:22 +0200
Subject: [PATCH] Rule: check for symbol error sentinel

This allows the sentinel to be used as return value.
---
 gsat.geany        |  4 +--
 src/lib/rule.c    |  6 ++++
 tests/test_rule.c | 80 ++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 70 insertions(+), 20 deletions(-)

diff --git a/gsat.geany b/gsat.geany
index dc8da5b..fd3745e 100644
--- a/gsat.geany
+++ b/gsat.geany
@@ -43,7 +43,7 @@ FILE_NAME_10=8070;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fp
 FILE_NAME_11=957;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Fsrc%2Flib%2Fgrammar.h;0;8
 FILE_NAME_12=6482;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Fsrc%2Flib%2Ffile.c;0;8
 FILE_NAME_13=1457;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Fsrc%2Flib%2Ffile.h;0;8
-FILE_NAME_14=2335;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Fsrc%2Flib%2Frule.c;0;8
+FILE_NAME_14=1688;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Fsrc%2Flib%2Frule.c;0;8
 FILE_NAME_15=1687;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Fsrc%2Flib%2Frule.h;0;8
 FILE_NAME_16=1282;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Fsrc%2Flib%2Fword.c;0;8
 FILE_NAME_17=908;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Fsrc%2Flib%2Fword.h;0;8
@@ -51,7 +51,7 @@ FILE_NAME_18=433;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2
 FILE_NAME_19=0;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Ftests%2Fno_test.sh;0;8
 FILE_NAME_20=51550;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Ftests%2Ftest_grammar.c;0;8
 FILE_NAME_21=17996;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Ftests%2Ftest_file.c;0;8
-FILE_NAME_22=2018;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Ftests%2Ftest_rule.c;0;8
+FILE_NAME_22=5286;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Ftests%2Ftest_rule.c;0;8
 FILE_NAME_23=1731;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDocuments%2Fprojects%2Fprgm%2Flanguage%2FGSAT%2Ftests%2Ftest_word.c;0;8
 
 [prjorg]
diff --git a/src/lib/rule.c b/src/lib/rule.c
index 2f337b7..a745d2d 100644
--- a/src/lib/rule.c
+++ b/src/lib/rule.c
@@ -76,6 +76,12 @@ insert_src (struct GR_Rule * rule, size_t index, symbol_t symbol,
 {
 	symbol_t * new_src;
 
+	if (SYMBOL_ERR == symbol)
+	{
+		set_status (status, E_VALUE, 2, "invalid symbol");
+		return FALSE;
+	}
+
 	new_src = realloc (rule->src, sizeof (symbol_t)
 	                             * (rule->src_n + 1));
 	if (NULL == new_src)
diff --git a/tests/test_rule.c b/tests/test_rule.c
index 1ac835b..2a9748b 100644
--- a/tests/test_rule.c
+++ b/tests/test_rule.c
@@ -71,28 +71,32 @@ START_TEST(test_rule_insert_no_status)
 	rule = GR_Rule_new (NULL);
 	ck_assert_ptr_ne (NULL, rule);
 
+	/* test - invalid symbol */
+	result = insert_src (rule, 0, SYMBOL_ERR, NULL);
+	ck_assert_int_eq (FALSE, result);
+
 	/* test */
-	result = insert_src (rule, 0, 0, NULL);
+	result = insert_src (rule, 0, 1, NULL);
 	ck_assert_int_eq (TRUE, result);
 
 	/* test - insert after */
-	result = insert_src (rule, 1, 1, NULL);
+	result = insert_src (rule, 1, 2, NULL);
 	ck_assert_int_eq (TRUE, result);
 
 	/* test - insert before */
-	result = insert_src (rule, 0, 2, NULL);
+	result = insert_src (rule, 0, 3, NULL);
 	ck_assert_int_eq (TRUE, result);
 
 	/* test - insert in between */
-	result = insert_src (rule, 1, 3, NULL);
+	result = insert_src (rule, 1, 4, NULL);
 	ck_assert_int_eq (TRUE, result);
 
 	/* check */
 	ck_assert_int_eq (4, rule->src_n);
-	ck_assert_int_eq (2, rule->src[0]);
-	ck_assert_int_eq (3, rule->src[1]);
-	ck_assert_int_eq (0, rule->src[2]);
-	ck_assert_int_eq (1, rule->src[3]);
+	ck_assert_int_eq (3, rule->src[0]);
+	ck_assert_int_eq (4, rule->src[1]);
+	ck_assert_int_eq (1, rule->src[2]);
+	ck_assert_int_eq (2, rule->src[3]);
 
 	/* cleanup */
 	GR_Rule_free (rule);
@@ -109,36 +113,42 @@ START_TEST(test_rule_insert_with_status)
 	rule = GR_Rule_new (NULL);
 	ck_assert_ptr_ne (NULL, rule);
 
+	/* test - invalid symbol */
+	_status_preinit(status);
+	result = insert_src (rule, 0, SYMBOL_ERR, &status);
+	ck_assert_int_eq (FALSE, result);
+	ck_assert_int_eq (E_VALUE, status.status);
+
 	/* test */
 	_status_preinit(status);
-	result = insert_src (rule, 0, 0, &status);
+	result = insert_src (rule, 0, 1, &status);
 	ck_assert_int_eq (TRUE, result);
 	ck_assert_int_eq (SUCCESS, status.status);
 
 	/* test - insert after */
 	_status_preinit(status);
-	result = insert_src (rule, 1, 1, &status);
+	result = insert_src (rule, 1, 2, &status);
 	ck_assert_int_eq (TRUE, result);
 	ck_assert_int_eq (SUCCESS, status.status);
 
 	/* test - insert before */
 	_status_preinit(status);
-	result = insert_src (rule, 0, 2, &status);
+	result = insert_src (rule, 0, 3, &status);
 	ck_assert_int_eq (TRUE, result);
 	ck_assert_int_eq (SUCCESS, status.status);
 
 	/* test - insert in between */
 	_status_preinit(status);
-	result = insert_src (rule, 1, 3, &status);
+	result = insert_src (rule, 1, 4, &status);
 	ck_assert_int_eq (TRUE, result);
 	ck_assert_int_eq (SUCCESS, status.status);
 
 	/* check */
 	ck_assert_int_eq (4, rule->src_n);
-	ck_assert_int_eq (2, rule->src[0]);
-	ck_assert_int_eq (3, rule->src[1]);
-	ck_assert_int_eq (0, rule->src[2]);
-	ck_assert_int_eq (1, rule->src[3]);
+	ck_assert_int_eq (3, rule->src[0]);
+	ck_assert_int_eq (4, rule->src[1]);
+	ck_assert_int_eq (1, rule->src[2]);
+	ck_assert_int_eq (2, rule->src[3]);
 
 	/* cleanup */
 	GR_Rule_free (rule);
@@ -155,21 +165,34 @@ START_TEST(test_rule_insert_insert_no_status)
 	ck_assert_ptr_ne (NULL, rule);
 
 	/* test insert - out of range */
-	result = GR_Rule_insert_source_symbol (rule, 1, 0, NULL);
+	result = GR_Rule_insert_source_symbol (rule, 1, 1, NULL);
 	ck_assert_int_eq (FALSE, result);
 
 	/* test insert */
 	result = GR_Rule_insert_source_symbol (rule, 0, 1, NULL);
 	ck_assert_int_eq (TRUE, result);
 
+	/* test insert - invalid symbol */
+	result = GR_Rule_insert_source_symbol (rule, 0, SYMBOL_ERR,
+	                                       NULL);
+	ck_assert_int_eq (FALSE, result);
+
 	/* test prepend */
 	result = GR_Rule_prepend_source_symbol (rule, 2, NULL);
 	ck_assert_int_eq (TRUE, result);
 
+	/* test prepend - invalid symbol */
+	result = GR_Rule_prepend_source_symbol (rule, SYMBOL_ERR, NULL);
+	ck_assert_int_eq (FALSE, result);
+
 	/* test append */
 	result = GR_Rule_append_source_symbol (rule, 3, NULL);
 	ck_assert_int_eq (TRUE, result);
 
+	/* test append - invalid symbol */
+	result = GR_Rule_append_source_symbol (rule, SYMBOL_ERR, NULL);
+	ck_assert_int_eq (FALSE, result);
+
 	/* check */
 	ck_assert_int_eq (3, rule->src_n);
 	ck_assert_int_eq (2, rule->src[0]);
@@ -193,7 +216,7 @@ START_TEST(test_rule_insert_insert_with_status)
 
 	/* test insert - out of range */
 	_status_preinit(status);
-	result = GR_Rule_insert_source_symbol (rule, 1, 0, &status);
+	result = GR_Rule_insert_source_symbol (rule, 1, 1, &status);
 	ck_assert_int_eq (FALSE, result);
 	ck_assert_int_eq (E_VALUE, status.status);
 
@@ -203,18 +226,39 @@ START_TEST(test_rule_insert_insert_with_status)
 	ck_assert_int_eq (TRUE, result);
 	ck_assert_int_eq (SUCCESS, status.status);
 
+	/* test insert - invalid symbol */
+	_status_preinit(status);
+	result = GR_Rule_insert_source_symbol (rule, 0, SYMBOL_ERR,
+	                                       &status);
+	ck_assert_int_eq (FALSE, result);
+	ck_assert_int_eq (E_VALUE, status.status);
+
 	/* test prepend */
 	_status_preinit(status);
 	result = GR_Rule_prepend_source_symbol (rule, 2, &status);
 	ck_assert_int_eq (TRUE, result);
 	ck_assert_int_eq (SUCCESS, status.status);
 
+	/* test prepend - invalid symbol */
+	_status_preinit(status);
+	result = GR_Rule_prepend_source_symbol (rule, SYMBOL_ERR,
+	                                        &status);
+	ck_assert_int_eq (FALSE, result);
+	ck_assert_int_eq (E_VALUE, status.status);
+
 	/* test append */
 	_status_preinit(status);
 	result = GR_Rule_append_source_symbol (rule, 3, &status);
 	ck_assert_int_eq (TRUE, result);
 	ck_assert_int_eq (SUCCESS, status.status);
 
+	/* test append - invalid symbol */
+	_status_preinit(status);
+	result = GR_Rule_append_source_symbol (rule, SYMBOL_ERR,
+	                                       &status);
+	ck_assert_int_eq (FALSE, result);
+	ck_assert_int_eq (E_VALUE, status.status);
+
 	/* check */
 	ck_assert_int_eq (3, rule->src_n);
 	ck_assert_int_eq (2, rule->src[0]);
-- 
GitLab