diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-05-29 22:52:10 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-05-29 22:52:10 -0300 |
| commit | f6c8c67094de3fe19f1e7871a7e78a91fb9bf3dd (patch) | |
| tree | 16d4bf88e2a3cc37a160d768fa26b82390796cb7 | |
| parent | e5b60ae075e571a29868993a5f0d191d91f8d266 (diff) | |
| download | game-f6c8c67094de3fe19f1e7871a7e78a91fb9bf3dd.tar.gz game-f6c8c67094de3fe19f1e7871a7e78a91fb9bf3dd.zip | |
finish `strings.cc` impl
| -rw-r--r-- | reference/game.c | 809 | ||||
| -rw-r--r-- | src/common.hh | 10 | ||||
| -rw-r--r-- | src/objects.cc | 16 | ||||
| -rw-r--r-- | src/strings.cc | 383 |
4 files changed, 397 insertions, 821 deletions
diff --git a/reference/game.c b/reference/game.c index e8bb7cd..55287d4 100644 --- a/reference/game.c +++ b/reference/game.c @@ -2667,815 +2667,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return;
}
-bool IsCountable(char *s)
-
-{
- bool bVar1;
- int iVar2;
- byte *pbVar3;
- byte *pbVar4;
- bool bVar5;
- bool bVar6;
- bool bVar7;
-
- iVar2 = 5;
- bVar5 = &stack0xfffffffc < (undefined1 *)0xc;
- bVar7 = &stack0x00000000 == (undefined1 *)0x10;
- pbVar3 = (byte *)s;
- pbVar4 = (byte *)"some ";
- do {
- if (iVar2 == 0) break;
- iVar2 = iVar2 + -1;
- bVar5 = *pbVar3 < *pbVar4;
- bVar7 = *pbVar3 == *pbVar4;
- pbVar3 = pbVar3 + 1;
- pbVar4 = pbVar4 + 1;
- } while (bVar7);
- bVar1 = false;
- bVar6 = (!bVar5 && !bVar7) < bVar5;
- bVar5 = (!bVar5 && !bVar7) == bVar5;
- if (!bVar5) {
- iVar2 = 2;
- pbVar3 = (byte *)s;
- pbVar4 = &DAT_080f02d3;
- do {
- if (iVar2 == 0) break;
- iVar2 = iVar2 + -1;
- bVar6 = *pbVar3 < *pbVar4;
- bVar5 = *pbVar3 == *pbVar4;
- pbVar3 = pbVar3 + 1;
- pbVar4 = pbVar4 + 1;
- } while (bVar5);
- if (!bVar5) {
- iVar2 = 3;
- pbVar3 = &DAT_080f02d6;
- do {
- if (iVar2 == 0) break;
- iVar2 = iVar2 + -1;
- bVar6 = (byte)*s < *pbVar3;
- bVar5 = *s == *pbVar3;
- s = (char *)((byte *)s + 1);
- pbVar3 = pbVar3 + 1;
- } while (bVar5);
- if ((!bVar6 && !bVar5) != bVar6) {
- return false;
- }
- }
- bVar1 = true;
- }
- return bVar1;
-}
-
-
-
-char * Plural(char *s,int Count)
-
-{
- bool bVar1;
- char cVar2;
- char cVar3;
- int iVar4;
- uint *puVar5;
- uint *puVar6;
- uint uVar7;
- uint uVar8;
- byte *pbVar9;
- byte *pbVar10;
- char *pcVar11;
- bool bVar12;
- bool bVar13;
- bool bVar14;
- undefined1 uVar15;
- char *pcVar16;
- size_t __n;
- char local_5c [3];
- char Last;
- char Help [50];
-
- Plural::ObjectNameString._0_4_ = Plural::ObjectNameString._0_4_ & 0xffffff00;
- if (s == (char *)0x0) {
- error(&DAT_080f0640);
- goto LAB_08051ff0;
- }
- strcpy(Plural::ObjectNameString,s);
- bVar12 = Count == 0;
- bVar14 = Count == 1;
- if (bVar14) goto LAB_08051ff0;
- iVar4 = 5;
- pbVar9 = (byte *)Plural::ObjectNameString;
- pbVar10 = (byte *)"some ";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- bVar12 = *pbVar9 < *pbVar10;
- bVar14 = *pbVar9 == *pbVar10;
- pbVar9 = pbVar9 + 1;
- pbVar10 = pbVar10 + 1;
- } while (bVar14);
- bVar1 = false;
- bVar13 = (!bVar12 && !bVar14) < bVar12;
- bVar12 = (!bVar12 && !bVar14) == bVar12;
- if (!bVar12) {
- iVar4 = 2;
- pbVar9 = (byte *)Plural::ObjectNameString;
- pbVar10 = &DAT_080f02d3;
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- bVar13 = *pbVar9 < *pbVar10;
- bVar12 = *pbVar9 == *pbVar10;
- pbVar9 = pbVar9 + 1;
- pbVar10 = pbVar10 + 1;
- } while (bVar12);
- if (!bVar12) {
- iVar4 = 3;
- pbVar9 = (byte *)Plural::ObjectNameString;
- pbVar10 = &DAT_080f02d6;
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- bVar13 = *pbVar9 < *pbVar10;
- bVar12 = *pbVar9 == *pbVar10;
- pbVar9 = pbVar9 + 1;
- pbVar10 = pbVar10 + 1;
- } while (bVar12);
- bVar1 = false;
- if ((!bVar13 && !bVar12) != bVar13) goto LAB_08051f2b;
- }
- bVar1 = true;
- }
-LAB_08051f2b:
- if (!bVar1) goto LAB_08051ff0;
- if (Plural::ObjectNameString[1] == 'n') {
- __n = 0x2f;
- pcVar16 = Plural::ObjectNameString + 3;
- }
- else {
- __n = 0x30;
- pcVar16 = Plural::ObjectNameString + 2;
- }
- memmove(Plural::ObjectNameString,pcVar16,__n);
- if (Count < 0) goto LAB_08051ff0;
- pcVar16 = strstr(Plural::ObjectNameString," of ");
- uVar15 = pcVar16 == (char *)0x0;
- if ((bool)uVar15) {
- local_5c[0] = '\0';
- }
- else {
- strcpy(local_5c,pcVar16);
- *pcVar16 = '\0';
- }
- iVar4 = 6;
- pcVar16 = Plural::ObjectNameString;
- pcVar11 = "knife";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- uVar15 = *pcVar16 == *pcVar11;
- pcVar16 = pcVar16 + 1;
- pcVar11 = pcVar11 + 1;
- } while ((bool)uVar15);
- if ((bool)uVar15) {
- Plural::ObjectNameString._6_2_ = SUB42(Plural::ObjectNameString._4_4_,2) & 0xff00;
- builtin_strncpy(Plural::ObjectNameString,"kniv",4);
- Plural::ObjectNameString[4] = 'e';
- Plural::ObjectNameString[5] = 's';
- }
- else {
- iVar4 = 0xf;
- pcVar16 = Plural::ObjectNameString;
- pcVar11 = "throwing knife";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- uVar15 = *pcVar16 == *pcVar11;
- pcVar16 = pcVar16 + 1;
- pcVar11 = pcVar11 + 1;
- } while ((bool)uVar15);
- if ((bool)uVar15) {
- builtin_strncpy(Plural::ObjectNameString,"throwing knives",0x10);
- }
- else {
- iVar4 = 0xd;
- pcVar16 = Plural::ObjectNameString;
- pcVar11 = "orc spearman";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- uVar15 = *pcVar16 == *pcVar11;
- pcVar16 = pcVar16 + 1;
- pcVar11 = pcVar11 + 1;
- } while ((bool)uVar15);
- if ((bool)uVar15) {
- Plural::ObjectNameString._12_4_ = Plural::ObjectNameString._12_4_ & 0xffffff00;
- builtin_strncpy(Plural::ObjectNameString,"orc spearmen",0xc);
- }
- else {
- iVar4 = 5;
- pcVar16 = Plural::ObjectNameString;
- pcVar11 = "deer";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- uVar15 = *pcVar16 == *pcVar11;
- pcVar16 = pcVar16 + 1;
- pcVar11 = pcVar11 + 1;
- } while ((bool)uVar15);
- if (!(bool)uVar15) {
- iVar4 = 10;
- pcVar16 = Plural::ObjectNameString;
- pcVar11 = "dead deer";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- uVar15 = *pcVar16 == *pcVar11;
- pcVar16 = pcVar16 + 1;
- pcVar11 = pcVar11 + 1;
- } while ((bool)uVar15);
- if (!(bool)uVar15) {
- iVar4 = 6;
- pcVar16 = Plural::ObjectNameString;
- pcVar11 = "sheep";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- uVar15 = *pcVar16 == *pcVar11;
- pcVar16 = pcVar16 + 1;
- pcVar11 = pcVar11 + 1;
- } while ((bool)uVar15);
- if (!(bool)uVar15) {
- iVar4 = 0xc;
- pcVar16 = Plural::ObjectNameString;
- pcVar11 = "black sheep";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- uVar15 = *pcVar16 == *pcVar11;
- pcVar16 = pcVar16 + 1;
- pcVar11 = pcVar11 + 1;
- } while ((bool)uVar15);
- if (!(bool)uVar15) {
- iVar4 = 5;
- pcVar16 = Plural::ObjectNameString;
- pcVar11 = "fish";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- uVar15 = *pcVar16 == *pcVar11;
- pcVar16 = pcVar16 + 1;
- pcVar11 = pcVar11 + 1;
- } while ((bool)uVar15);
- if (!(bool)uVar15) {
- puVar6 = (uint *)Plural::ObjectNameString;
- do {
- puVar5 = puVar6;
- uVar7 = *puVar5 + 0xfefefeff & ~*puVar5;
- uVar8 = uVar7 & 0x80808080;
- puVar6 = puVar5 + 1;
- } while (uVar8 == 0);
- bVar12 = (uVar7 & 0x8080) == 0;
- if (bVar12) {
- uVar8 = uVar8 >> 0x10;
- }
- if (bVar12) {
- puVar6 = (uint *)((int)puVar5 + 6);
- }
- if (1 < (int)puVar6 +
- (-0x8128bc3 - (uint)CARRY1((byte)uVar8,(byte)uVar8))) {
- puVar6 = (uint *)Plural::ObjectNameString;
- do {
- puVar5 = puVar6;
- uVar7 = *puVar5 + 0xfefefeff & ~*puVar5;
- uVar8 = uVar7 & 0x80808080;
- puVar6 = puVar5 + 1;
- } while (uVar8 == 0);
- bVar12 = (uVar7 & 0x8080) == 0;
- if (bVar12) {
- uVar8 = uVar8 >> 0x10;
- }
- if (bVar12) {
- puVar6 = (uint *)((int)puVar5 + 6);
- }
- iVar4 = toLower((int)*(char *)((int)puVar6 +
- (-4 - (uint)CARRY1((byte)uVar8
- ,(byte)
- uVar8))));
- cVar2 = (char)iVar4;
- puVar6 = (uint *)Plural::ObjectNameString;
- do {
- puVar5 = puVar6;
- uVar7 = *puVar5 + 0xfefefeff & ~*puVar5;
- uVar8 = uVar7 & 0x80808080;
- puVar6 = puVar5 + 1;
- } while (uVar8 == 0);
- bVar12 = (uVar7 & 0x8080) == 0;
- if (bVar12) {
- uVar8 = uVar8 >> 0x10;
- }
- if (bVar12) {
- puVar6 = (uint *)((int)puVar5 + 6);
- }
- iVar4 = toLower((int)*(char *)((int)puVar6 +
- (-5 - (uint)CARRY1((byte)uVar8
- ,(byte)
- uVar8))));
- if (((cVar2 == 's') || (cVar2 == 'x')) ||
- ((cVar3 = (char)iVar4, cVar2 == 'h' &&
- ((cVar3 == 's' || (cVar3 == 'c')))))) {
-LAB_08052224:
- pcVar16 = "es";
- }
- else {
- if ((cVar2 == 'y') &&
- ((((cVar3 != 'a' && (cVar3 != 'e')) && (cVar3 != 'i')
- ) && ((cVar3 != 'o' && (cVar3 != 'u')))))) {
- puVar6 = (uint *)Plural::ObjectNameString;
- do {
- puVar5 = puVar6;
- uVar7 = *puVar5 + 0xfefefeff & ~*puVar5;
- uVar8 = uVar7 & 0x80808080;
- puVar6 = puVar5 + 1;
- } while (uVar8 == 0);
- bVar12 = (uVar7 & 0x8080) == 0;
- if (bVar12) {
- uVar8 = uVar8 >> 0x10;
- }
- if (bVar12) {
- puVar6 = (uint *)((int)puVar5 + 6);
- }
- *(undefined1 *)
- ((int)puVar6 +
- (-4 - (uint)CARRY1((byte)uVar8,(byte)uVar8))) =
- 0x69;
- goto LAB_08052224;
- }
- if ((cVar2 == 'f') && (cVar3 == 'l')) {
- puVar6 = (uint *)Plural::ObjectNameString;
- do {
- puVar5 = puVar6;
- uVar7 = *puVar5 + 0xfefefeff & ~*puVar5;
- uVar8 = uVar7 & 0x80808080;
- puVar6 = puVar5 + 1;
- } while (uVar8 == 0);
- bVar12 = (uVar7 & 0x8080) == 0;
- if (bVar12) {
- uVar8 = uVar8 >> 0x10;
- }
- if (bVar12) {
- puVar6 = (uint *)((int)puVar5 + 6);
- }
- *(undefined1 *)
- ((int)puVar6 +
- (-4 - (uint)CARRY1((byte)uVar8,(byte)uVar8))) =
- 0x76;
- goto LAB_08052224;
- }
- if (cVar2 == 'o') goto LAB_08052224;
- pcVar16 = "s";
- }
- strcat(Plural::ObjectNameString,pcVar16);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- strcat(Plural::ObjectNameString,local_5c);
- strcpy(local_5c,Plural::ObjectNameString);
- if (Count != 0) {
- snprintf(Plural::ObjectNameString,0x32,"%d %s",Count,local_5c);
- }
-LAB_08051ff0:
- return Plural::ObjectNameString;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: start
-
-char * SearchForWord(char *Pattern,char *Text)
-
-{
- char cVar1;
- char cVar2;
- bool bVar3;
- bool bVar4;
- int iVar5;
- int iVar6;
- uint count;
- uint uVar7;
- char *c;
- char *Text_00;
- uint uStack_18;
- bool WholeWord;
- uint PatternLength;
- bool start;
-
- if ((Pattern == (char *)0x0) || (*Pattern == '\0')) {
- Text_00 = &DAT_080f0680;
- }
- else {
- if (Text != (char *)0x0) {
- bVar4 = true;
- uStack_18 = strlen(Pattern);
- cVar1 = Pattern[uStack_18 - 1];
- if (cVar1 == '$') {
- uStack_18 = uStack_18 - 1;
- }
- cVar2 = *Text;
- do {
- if (cVar2 == '\0') {
- return (char *)0x0;
- }
- bVar3 = isSpace((int)cVar2);
- if (bVar3) {
- bVar4 = true;
- }
- else if (bVar4) {
- uVar7 = 0;
- do {
- if (uVar7 == uStack_18) {
- if (cVar1 != '$') {
- return Text;
- }
- bVar4 = isAlpha((int)Text[uVar7]);
- if ((!bVar4) && (bVar4 = isDigit((int)Text[uVar7]), !bVar4)) {
- return Text;
- }
-LAB_080523f6:
- bVar4 = false;
- break;
- }
- iVar5 = toLower((int)Text[uVar7]);
- iVar6 = toLower((int)Pattern[uVar7]);
- if (iVar5 != iVar6) goto LAB_080523f6;
- uVar7 = uVar7 + 1;
- } while (uVar7 <= uStack_18);
- }
- Text = Text + 1;
- cVar2 = *Text;
- } while( true );
- }
- Text_00 = &DAT_080f06c0;
- }
- error(Text_00);
- return (char *)0x0;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: start
-
-char * SearchForNumber(int Count,char *Text)
-
-{
- char cVar1;
- bool bVar2;
- bool bVar3;
- char *c;
- int ofs;
- int iVar4;
- bool start;
-
- if (Count < 1) {
- error("SearchForNumber: Illegale Suchnummer %d.\n",Count);
- }
- else if (Text == (char *)0x0) {
- error(&DAT_080f0700);
- }
- else {
- bVar2 = true;
- cVar1 = *Text;
- while (cVar1 != '\0') {
- bVar3 = isSpace((int)cVar1);
- if (bVar3) {
- bVar2 = true;
- }
- else if (bVar2) {
- bVar2 = false;
- bVar3 = isDigit((int)*Text);
- if (bVar3) {
- iVar4 = 0;
- do {
- iVar4 = iVar4 + 1;
- if ((Text[iVar4] == '\0') || (bVar3 = isSpace((int)Text[iVar4]), bVar3)) {
- Count = Count + -1;
- if (Count == 0) {
- return Text;
- }
- break;
- }
- bVar3 = isDigit((int)Text[iVar4]);
- } while (bVar3);
- }
- }
- Text = Text + 1;
- cVar1 = *Text;
- }
- }
- return (char *)0x0;
-}
-
-
-
-bool MatchString(char *Pattern,char *String)
-
-{
- char cVar1;
- int iVar2;
- char c;
- size_t sVar3;
- int iVar4;
- int iVar5;
- int i;
- int iVar6;
- int *piVar7;
- int *piVar8;
- int *piVar9;
- bool bVar10;
- undefined4 uStackY_60;
- char *Text;
- int aiStack_58 [3];
- int *local_4c;
- int local_48;
- int local_44;
- int i_1;
- int ins;
- int del;
- int edit;
- int local_30;
- int j;
- int_0__0_ *d;
- size_t local_24;
- size_t local_20;
- int local_1c [3];
-
- d = &stack0xffffffa4;
- if (Pattern == (char *)0x0) {
- Text = "MatchString: Pattern ist NULL.\n";
- }
- else {
- if (String != (char *)0x0) {
- uStackY_60 = 0x805254d;
- d = &stack0xffffffa4;
- local_20 = strlen(String);
- uStackY_60 = 0x805255b;
- sVar3 = strlen(Pattern);
- local_24 = sVar3;
- iVar2 = -(sVar3 * 4 + 0x13 + local_20 * (sVar3 * 4 + 4) & 0xfffffff0);
- iVar6 = 0;
- piVar8 = (int *)((int)aiStack_58 + iVar2);
- j = (int)piVar8;
- if (-1 < (int)local_20) {
- do {
- *piVar8 = iVar6;
- iVar6 = iVar6 + 1;
- piVar8 = piVar8 + sVar3 + 1;
- } while (iVar6 <= (int)local_20);
- }
- local_30 = 1;
- if (0 < (int)local_24) {
- aiStack_58[2] = 4;
- local_4c = (int *)(j + 4);
- do {
- edit = (int)(Pattern + local_30);
- cVar1 = (Pattern + local_30)[-1];
- i_1 = 1;
- ins = 1;
- bVar10 = cVar1 == '*';
- if (bVar10) {
- ins = 0;
- i_1 = 0;
- }
- del = (int)!bVar10;
- ins = (int)!bVar10;
- i_1 = (int)!bVar10;
- iVar6 = 0;
- if (cVar1 != '?') {
- iVar6 = del;
- }
- del = iVar6;
- *(int *)(j + aiStack_58[2]) = ins + *(int *)(j + -4 + aiStack_58[2]);
- local_44 = 1;
- if (0 < (int)local_20) {
- local_48 = local_24 * 4 + 4;
- piVar9 = local_4c + local_24 + 1;
- piVar8 = local_4c;
- do {
- *(int *)(&stack0xffffffa4 + iVar2) = (int)String[local_44 + -1];
- *(undefined4 *)((int)&uStackY_60 + iVar2) = 0x8052653;
- iVar4 = toLower(*(int *)(&stack0xffffffa4 + iVar2));
- *(int *)(&stack0xffffffa4 + iVar2) = (int)*(char *)(edit + -1);
- *(undefined4 *)((int)&uStackY_60 + iVar2) = 0x8052664;
- iVar5 = toLower(*(int *)(&stack0xffffffa4 + iVar2));
- iVar6 = 0;
- if (iVar4 != iVar5) {
- iVar6 = del;
- }
- local_1c[2] = i_1 + *piVar8;
- local_1c[1] = ins + piVar9[-1];
- piVar7 = local_1c + 1;
- if (i_1 + *piVar8 <= ins + piVar9[-1]) {
- piVar7 = local_1c + 2;
- }
- local_1c[0] = iVar6 + piVar8[-1];
- if (iVar6 + piVar8[-1] < *piVar7) {
- piVar7 = local_1c;
- }
- *piVar9 = *piVar7;
- local_44 = local_44 + 1;
- piVar9 = (int *)((int)piVar9 + local_48);
- piVar8 = (int *)((int)piVar8 + local_48);
- } while (local_44 <= (int)local_20);
- }
- local_30 = local_30 + 1;
- local_4c = local_4c + 1;
- aiStack_58[2] = aiStack_58[2] + 4;
- } while (local_30 <= (int)local_24);
- }
- return *(int *)(local_20 * (local_24 * 4 + 4) + local_24 * 4 + j) == 0;
- }
- Text = "MatchString: String ist NULL.\n";
- }
- uStackY_60 = 0x805271f;
- error(Text);
- return false;
-}
-
-
-
-void AddSlashes(char *Destination,char *Source)
-
-{
- char cVar1;
-
- if (Source == (char *)0x0) {
- Destination = "AddSlashes: Source ist NULL.\n";
- }
- else {
- if (Destination != (char *)0x0) {
- cVar1 = *Source;
- while (cVar1 != '\0') {
- if (('!' < cVar1) && (((cVar1 < '$' || (cVar1 == '\'')) || (cVar1 == '\\')))) {
- *Destination = '\\';
- Destination = Destination + 1;
- cVar1 = *Source;
- }
- *Destination = cVar1;
- Source = Source + 1;
- Destination = Destination + 1;
- cVar1 = *Source;
- }
- *Destination = '\0';
- return;
- }
- Destination = "AddSlashes: Destination ist NULL.\n";
- }
- error(Destination);
- return;
-}
-
-
-
-void Trim(char *Text)
-
-{
- bool bVar1;
- size_t sVar2;
- int i;
- int iVar3;
-
- if (Text == (char *)0x0) {
- error("Trim: Text ist NULL.\n");
- return;
- }
- iVar3 = 0;
- while ((Text[iVar3] != '\0' && (bVar1 = isSpace((int)Text[iVar3]), bVar1))) {
- iVar3 = iVar3 + 1;
- }
- sVar2 = strlen(Text + 1);
- memmove(Text,Text + iVar3,sVar2 + 1);
- sVar2 = strlen(Text);
- while( true ) {
- if ((int)sVar2 < 1) {
- return;
- }
- bVar1 = isSpace((int)Text[sVar2 - 1]);
- if (!bVar1) break;
- Text[sVar2 - 1] = '\0';
- sVar2 = sVar2 - 1;
- }
- return;
-}
-
-
-
-void Trim(char *Destination,char *Source)
-
-{
- bool bVar1;
- size_t sVar2;
- int i;
- int iVar3;
-
- if (Source == (char *)0x0) {
- Destination = "Trim: Source ist NULL.\n";
- }
- else {
- if (Destination != (char *)0x0) {
- iVar3 = 0;
- while ((Source[iVar3] != '\0' && (bVar1 = isSpace((int)Source[iVar3]), bVar1))) {
- iVar3 = iVar3 + 1;
- }
- strcpy(Destination,Source + iVar3);
- sVar2 = strlen(Destination);
- while( true ) {
- if ((int)sVar2 < 1) {
- return;
- }
- bVar1 = isSpace((int)Destination[sVar2 - 1]);
- if (!bVar1) break;
- Destination[sVar2 - 1] = '\0';
- sVar2 = sVar2 - 1;
- }
- return;
- }
- Destination = "Trim: Destination ist NULL.\n";
- }
- error(Destination);
- return;
-}
-
-
-
-void ChangeWildcards(char *String)
-
-{
- char cVar1;
- size_t sVar2;
- uint i;
- uint uVar3;
-
- if (String != (char *)0x0) {
- uVar3 = 0;
- while( true ) {
- sVar2 = strlen(String);
- if (sVar2 <= uVar3) break;
- cVar1 = String[uVar3];
- if (cVar1 == '*') {
- String[uVar3] = '%';
- cVar1 = '%';
- }
- if (cVar1 == '?') {
- String[uVar3] = '_';
- }
- uVar3 = uVar3 + 1;
- }
- return;
- }
- error("ChangeWildcards: String ist NULL.\n");
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: start
-
-char * Capitals(char *Text)
-
-{
- bool bVar1;
- bool bVar2;
- size_t sVar3;
- int iVar4;
- int i;
- int iVar5;
- bool start;
-
- iVar5 = 0;
- bVar1 = true;
- while( true ) {
- sVar3 = strlen(Text);
- if ((int)sVar3 <= iVar5) break;
- bVar2 = isAlpha((int)Text[iVar5]);
- if (bVar2) {
- if (bVar1) {
- iVar4 = toUpper((int)Text[iVar5]);
- Text[iVar5] = (char)iVar4;
- }
- bVar1 = false;
- }
- else {
- bVar1 = true;
- }
- iVar5 = iVar5 + 1;
- }
- return Text;
-}
-
void __tcf_0(void *param_1)
{
diff --git a/src/common.hh b/src/common.hh index 33fd694..8bf7fca 100644 --- a/src/common.hh +++ b/src/common.hh @@ -125,6 +125,16 @@ void CleanupDynamicStrings(void); void InitStrings(void); void ExitStrings(void); +bool IsCountable(const char *s); +const char *Plural(const char *s, int Count); +const char *SearchForWord(const char *Pattern, const char *Text); +const char *SearchForNumber(int Count, const char *Text); +bool MatchString(const char *Pattern, const char *String); +void AddSlashes(char *Destination, const char *Source); +void Trim(char *Text); +void Trim(char *Destination, const char *Source); +char *Capitals(char *Text); + // time.cc // ============================================================================= extern uint32 RoundNr; diff --git a/src/objects.cc b/src/objects.cc index e6903cd..f617fb9 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -321,21 +321,13 @@ const char *ObjectType::getName(int Count){ return NULL; } - // TODO(fusion): This is yet another rabbit hole. I'm not sure why we have - // the object name copied to the stack when `Plural` returns its own static - // buffer. -#if 0 - char ObjectName[50]; TObjectType *TypeP = ObjectTypes.at(this->TypeID); - if(Type->Name != NULL){ - strcpy(ObjectName, TypeP->Name); - }else{ - ObjectName[0] = 0; + const char *Name = TypeP->Name; + if(Name == NULL){ + Name = ""; } - return Plural(ObjectName, Count); -#endif - return "Unnamed"; + return Plural(Name, Count); } const char *ObjectType::getDescription(void){ diff --git a/src/strings.cc b/src/strings.cc index 41fdc44..aef9a81 100644 --- a/src/strings.cc +++ b/src/strings.cc @@ -214,3 +214,386 @@ void InitStrings(void){ void ExitStrings(void){ // no-op } + +// String Utility +// ============================================================================= +// TODO(fusion): I'm not sure why we have these separate from the other string +// utility defined in `util.cc`. We should probably just move them all here. + +bool IsCountable(const char *s){ + if(strncmp(s, "some ", 5) == 0){ + return false; + } + + return strncmp(s, "a ", 2) == 0 + || strncmp(s, "an ", 3) == 0; +} + +const char *Plural(const char *s, int Count){ + static char ObjectNameString[50]; + + ObjectNameString[0] = 0; + if(s == NULL){ + error("Plural: Übergebener String existiert nicht.\n"); + return ObjectNameString; + } + + strcpy(ObjectNameString, s); + if(Count == 1 || !IsCountable(ObjectNameString)){ + return ObjectNameString; + } + + // NOTE(fusion): `IsCountable` will only return true for `a XXXX` or `an XXXX`. + if(ObjectNameString[1] == 'n'){ + memmove(&ObjectNameString[0], + &ObjectNameString[3], + sizeof(ObjectNameString) - 3); + }else{ + memmove(&ObjectNameString[0], + &ObjectNameString[2], + sizeof(ObjectNameString) - 2); + } + + if(Count < 0){ + return ObjectNameString; + } + + char Help[sizeof(ObjectNameString)]; + if(char *Suffix = strstr(ObjectNameString, " of ")){ + strcpy(Help, Suffix); + Suffix[0] = 0; + }else{ + Help[0] = 0; + } + + // TODO(fusion): This method for pluralization is limited and incomplete but + // it probably works with the current set of object names. + if(strcmp(ObjectNameString, "knife") == 0){ + strcpy(ObjectNameString, "knives"); + }else if(strcmp(ObjectNameString, "throwing knife") == 0){ + strcpy(ObjectNameString, "throwing knives"); + }else if(strcmp(ObjectNameString, "orc spearman") == 0){ + strcpy(ObjectNameString, "orc spearmen"); + }else if(strcmp(ObjectNameString, "deer") != 0 + && strcmp(ObjectNameString, "dead deer") != 0 + && strcmp(ObjectNameString, "sheep") != 0 + && strcmp(ObjectNameString, "black sheep") != 0 + && strcmp(ObjectNameString, "fish") != 0){ + int NameLen = (int)strlen(ObjectNameString); + if(NameLen > 0){ + int Last = toLower(ObjectNameString[NameLen - 1]); + int Prev = 0; + if(NameLen > 1){ + Prev = toLower(ObjectNameString[NameLen - 2]); + } + + if(Last == 's' || Last == 'x' + || (Last == 'h' && (Prev == 's' || Prev == 'c'))){ + strcat(ObjectNameString, "es"); + }else if(Last == 'y' && Prev != 'a' && Prev != 'e' + && Prev != 'i' && Prev != 'o' && Prev != 'u'){ + ObjectNameString[NameLen - 1] = 'i'; + strcat(ObjectNameString, "es"); + }else if(Last == 'f' && Prev == 'l'){ + ObjectNameString[NameLen - 1] = 'v'; + strcat(ObjectNameString, "es"); + }else if(Last == 'o'){ + strcat(ObjectNameString, "es"); + }else{ + strcat(ObjectNameString, "s"); + } + } + } + + strcat(ObjectNameString, Help); + if(Count != 0){ + strcpy(Help, ObjectNameString); + snprintf(ObjectNameString, sizeof(ObjectNameString), "%d %s", Count, Help); + } + + return ObjectNameString; +} + +const char *SearchForWord(const char *Pattern, const char *Text){ + if(Pattern == NULL || Pattern[0] == 0){ + error("SearchForWord: Übergebenes Suchwort existiert nicht.\n"); + return NULL; + } + + if(Text == NULL){ + error("SearchForWord: Übergebener Text existiert nicht.\n"); + return NULL; + } + + int PatternLength = (int)strlen(Pattern); + bool WholeWord = false; + if(Pattern[PatternLength - 1] == '$'){ + PatternLength -= 1; + WholeWord = true; + } + + bool WordStart = true; + const char *Match = NULL; + for(int i = 0; Text[i] != 0; i += 1){ + // TODO(fusion): The original function would only check for spaces to + // determine the beginning of a word which can be problematic for sentences + // with punctuation. + //if(isSpace(Text[i])){ + if(!isAlpha(Text[i]) && !isDigit(Text[i])){ + WordStart = true; + }else if(WordStart){ + int j = 0; + while(j < PatternLength){ + if(toLower(Pattern[j]) != toLower(Text[i + j])){ + break; + } + j += 1; + } + + if(j == PatternLength){ + if(!WholeWord || (!isAlpha(Text[i + j]) && !isDigit(Text[i + j]))){ + Match = &Text[i]; + break; + } + } + + WordStart = false; + } + } + + return Match; +} + +const char *SearchForNumber(int Count, const char *Text){ + if(Count < 1){ + error("SearchForNumber: Illegale Suchnummer %d.\n", Count); + return NULL; + } + + if(Text == NULL){ + error("SearchForNumber: Übergebener Text existiert nicht.\n"); + return NULL; + } + + bool WordStart = true; + const char *Match = NULL; + for(int i = 0; Text[i] != 0; i += 1){ + // TODO(fusion): Same as `SearchForWord`. + //if(isSpace(Text[i])){ + if(!isAlpha(Text[i]) && !isDigit(Text[i])){ + WordStart = true; + }else if(WordStart){ + int j = 0; + while(isDigit(Text[i + j])){ + j += 1; + } + + // TODO(fusion): Same as `SearchForWord`. + //if(j > 0 && (Text[i + j] == 0 || isSpace(Text[i + j]))){ + if(j > 0 && !isAlpha(Text[i + j])){ + Count -= 1; + if(Count == 0){ + Match = &Text[i]; + break; + } + } + + WordStart = false; + } + } + + return Match; +} + +bool MatchString(const char *Pattern, const char *String){ + if(Pattern == NULL){ + error("MatchString: Pattern ist NULL.\n"); + return false; + } + + if(String == NULL){ + error("MatchString: String ist NULL.\n"); + return false; + } + + // NOTE(fusion): The original function was allocating an integer table on + // the stack, with dimensions (StringLength + 1) x (PatternLength + 1) to + // compute the edit distance. This made the decompiled version difficult + // to read and could potentially blow up the stack for large inputs. + // We'll use a fixed buffer instead, that will store the distances for the + // last and current table rows which is all is needed to compute the same + // edit distance. + + int StringLength = (int)strlen(String); + int PatternLength = (int)strlen(Pattern); + + constexpr int MaxStringLength = 255; + if(StringLength > MaxStringLength){ + error("MatchString: String is too large (Length = %d, MaxLength = %d)\n", + StringLength, MaxStringLength); + return false; + } + + int DistanceBuffer[2 * (MaxStringLength + 1)] = {}; + int *PrevRow = &DistanceBuffer[0]; + int *CurRow = &DistanceBuffer[StringLength + 1]; + for(int i = 0; i < (StringLength + 1); i += 1){ + PrevRow[i] = i; + } + + for(int i = 0; i < PatternLength; i += 1){ + int Ins = (Pattern[i] != '*'); + int Del = (Pattern[i] != '*'); + CurRow[0] = PrevRow[0] + Del; + for(int j = 0; j < StringLength; j += 1){ + int Edit = (Pattern[i] != '?' + && toLower(Pattern[i]) != toLower(String[j])); + + int Min = PrevRow[j + 1] + Ins; + if(Min > (PrevRow[j] + Edit)){ + Min = PrevRow[j] + Edit; + } + if(Min > (CurRow[j] + Del)){ + Min = CurRow[j] + Del; + } + + CurRow[j + 1] = Min; + } + + std::swap(PrevRow, CurRow); + } + + return PrevRow[StringLength] == 0; +} + +// TODO(fusion): This function is unsafe like `strcpy`. +void AddSlashes(char *Destination, const char *Source){ + if(Source == NULL){ + error("AddSlashes: Source ist NULL.\n"); + return; + } + + if(Destination == NULL){ + error("AddSlashes: Destination ist NULL.\n"); + return; + } + + int ReadIndex = 0; + int WriteIndex = 0; + while(Source[ReadIndex] != 0){ + if(Source[ReadIndex] == '"' || Source[ReadIndex] == '#' + || Source[ReadIndex] == '\'' || Source[ReadIndex] == '\\'){ + Destination[WriteIndex] = '\\'; + WriteIndex += 1; + } + + Destination[WriteIndex] = Source[ReadIndex]; + WriteIndex += 1; + ReadIndex += 1; + } + + Destination[WriteIndex] = 0; + WriteIndex += 1; +} + +void Trim(char *Text){ + if(Text == NULL){ + error("Trim: Text ist NULL.\n"); + return; + } + + // NOTE(fusion): `Start` is inclusive. + int Start = 0; + while(Text[Start] != 0 && isSpace(Text[Start])){ + Start += 1; + } + + int OldLength = Start; + while(Text[OldLength] != 0){ + OldLength += 1; + } + + if(Start < OldLength){ + // NOTE(fusion): `End` is inclusive. + int End = OldLength - 1; + while(End > Start && isSpace(Text[End])){ + End -= 1; + } + + int NewLength = End - Start + 1; + memmove(&Text[0], &Text[Start], NewLength); + Text[NewLength] = 0; + }else{ + Text[0] = 0; + } +} + +// TODO(fusion): This is a copy of the function above, except that we write to +// `Destination` instead of modifying the original string. It is unsafe as `strcpy`. +void Trim(char *Destination, const char *Source){ + if(Source == NULL){ + error("Trim: Source ist NULL.\n"); + return; + } + + if(Destination == NULL){ + error("Trim: Destination ist NULL.\n"); + return; + } + + int Start = 0; + while(Source[Start] != 0 && isSpace(Source[Start])){ + Start += 1; + } + + int OldLength = Start; + while(Source[OldLength] != 0){ + OldLength += 1; + } + + if(Start < OldLength){ + // NOTE(fusion): `End` is inclusive. + int End = OldLength - 1; + while(End > Start && isSpace(Source[End])){ + End -= 1; + } + + int NewLength = End - Start + 1; + memcpy(&Destination[0], &Source[Start], NewLength); + Destination[NewLength] = 0; + }else{ + Destination[0] = 0; + } +} + +void ChangeWildcards(char *String){ + if(String == NULL){ + error("ChangeWildcards: String ist NULL.\n"); + return; + } + + for(int i = 0; String[i] != 0; i += 1){ + if(String[i] == '*'){ + String[i] = '%'; + }else if(String[i] == '?'){ + String[i] = '_'; + } + } +} + +char *Capitals(char *Text){ + bool WordStart = true; + for(int i = 0; Text[i] != 0; i += 1){ + // TODO(fusion): The original function wouldn't consider digits which + // I'd argue is a mistake if there is a number prefixing a word. + if(!isAlpha(Text[i]) && !isDigit(Text[i])){ + WordStart = true; + }else if(WordStart){ + if(isAlpha(Text[i])){ + Text[i] = toUpper(Text[i]); + } + WordStart = false; + } + } + return Text; +} |
