/* rescomp.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Compiler fuer Message-Dateien */
/* */
/* 17. 5.1998 Symbol gegen Mehrfachinklusion eingebaut */
/* 5. 7.1998 zusaetzliche Sonderzeichen */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "be_le.h"
#include "strutil.h"
#include "bpemu.h"
/*****************************************************************************/
typedef struct _TMsgList
{
struct _TMsgList *Next;
LongInt Position;
char *Contents;
} TMsgList,*PMsgList;
typedef struct
{
PMsgList Messages,LastMessage;
char *CtryName;
LongInt *CtryCodes,CtryCodeCnt;
LongInt FilePos,HeadLength,TotLength;
} TMsgCat,*PMsgCat;
typedef struct
{
char *AbbString,*Character;
} TransRec;
#define IO_RETCODE_SRC 2
#define IO_RETCODE_RSC 3
#define IO_RETCODE_MSG 4
#define IO_RETCODE_MSH 5
/*****************************************************************************/
#ifdef __TURBOC__
unsigned _stklen = 16384;
#endif
static char *IdentString = "AS Message Catalog - not readable\n\032\004";
static LongInt MsgCounter;
static PMsgCat MsgCats;
static LongInt CatCount, DefCat;
static const char *p_msg_file_name = NULL, *p_msh_file_name = NULL;
static FILE *p_src_file, *p_msg_file, *p_rsc_file, *p_msh_file;
static size_t bytes_written;
static TransRec TransRecs[] =
{
{ "\\n" , "\n" },
{ NULL , NULL }
};
/*****************************************************************************/
typedef struct _TIncList
{
struct _TIncList *Next;
FILE *Contents;
} TIncList,*PIncList;
PIncList IncList = NULL;
void WrError(Word Num)
{
(void)Num;
}
static void fwritechk(const char *pArg, int retcode,
const void *pBuffer, size_t size, size_t nmemb, FILE *pFile)
{
size_t res;
res
= fwrite(pBuffer
, size
, nmemb
, pFile
);
if (res != nmemb)
{
}
}
static FILE *fopenchk(const char *pName, int retcode, const char *pOpenMode)
{
FILE *pRes;
pRes
= fopen(pName
, pOpenMode
);
if (!pRes)
{
}
return pRes;
}
static void GetLine(char *Dest)
{
PIncList OneFile;
ReadLn(p_src_file, Dest);
if (!as_strncasecmp(Dest, "INCLUDE", 7))
{
OneFile
= (PIncList
) malloc(sizeof(TIncList
));
OneFile->Next = IncList; OneFile->Contents = p_src_file;
IncList = OneFile;
strmov(Dest, Dest + 7); KillPrefBlanks(Dest); KillPrefBlanks(Dest);
p_src_file = fopenchk(Dest, 2, "r");
GetLine(Dest);
}
if (feof(p_src_file
) && IncList
)
{
OneFile = IncList; IncList = OneFile->Next;
p_src_file
= OneFile
->Contents
; free(OneFile
);
}
}
/*****************************************************************************/
static void SynError(char *LinePart)
{
fprintf(stderr
, "syntax error : %s\n", LinePart
); exit(10);
}
/*---------------------------------------------------------------------------*/
static void Process_LANGS(char *Line)
{
char NLine[1024], *p, *p2, *p3, *end, z, Part[1024];
PMsgCat PCat;
int num;
strmaxcpy(NLine, Line, 1024);
KillPrefBlanks(NLine); KillPostBlanks(NLine);
p = NLine; z = 0;
while (*p)
{
for (; *p && !as_isspace(*p); p++);
for (; *p && as_isspace(*p); p++);
z++;
}
MsgCats
= (PMsgCat
) malloc(sizeof(TMsgCat
) * (CatCount
= z
)); p
= NLine
;
for (z = 0, PCat = MsgCats; z < CatCount; z++, PCat++)
{
PCat->Messages = NULL;
PCat->TotLength = 0;
PCat->CtryCodeCnt = 0;
for (p2 = p; *p2 && !as_isspace(*p2); p2++);
if (*p2 == '\0')
else
{
for (p = p2 + 1; *p && as_isspace(*p2); p++); /* TODO: p instead of p2? */
}
if ((!*Part
) || (Part
[strlen(Part
)-1] != ')')) SynError
(Part
);
Part
[strlen(Part
) - 1] = '\0';
if (!p2)
SynError(Part);
*p2 = '\0';
PCat->CtryName = as_strdup(Part); p2++;
do
{
for (p3 = p2; ((*p3) && (*p3 != ',')); p3++);
switch (*p3)
{
case '\0':
num
= strtol(p2
, &end
, 10); p2
= p3
;
break;
case ',':
*p3
= '\0'; num
= strtol(p2
, &end
, 10); p2
= p3
+ 1;
break;
default:
num = 0;
break;
}
if (*end) SynError("numeric format");
PCat->CtryCodes=(PCat->CtryCodeCnt == 0) ?
(LongInt
*) malloc(sizeof(LongInt
)) :
(LongInt
*) realloc(PCat
->CtryCodes
, sizeof(LongInt
) * (PCat
->CtryCodeCnt
+ 1));
PCat->CtryCodes[PCat->CtryCodeCnt++] = num;
}
while (*p2!='\0');
}
}
static void Process_DEFAULT(char *Line)
{
PMsgCat z;
if (!CatCount) SynError("DEFAULT before LANGS");
KillPrefBlanks(Line); KillPostBlanks(Line);
for (z = MsgCats; z < MsgCats + CatCount; z++)
if (!as_strcasecmp(z->CtryName,Line))
break;
if (z >= MsgCats + CatCount)
SynError("unknown country name in DEFAULT");
DefCat = z - MsgCats;
}
static void Process_MESSAGE(char *Line)
{
char Msg[4096];
String OneLine;
int l;
PMsgCat z;
TransRec *PRec;
PMsgList List;
Boolean Cont;
KillPrefBlanks(Line); KillPostBlanks(Line);
if (p_rsc_file
) fprintf(p_rsc_file
, "#define Num_%s %d\n", Line
, MsgCounter
);
MsgCounter++;
for (z = MsgCats; z < MsgCats + CatCount; z++)
{
*Msg = '\0';
do
{
GetLine(OneLine); KillPrefBlanks(OneLine); KillPostBlanks(OneLine);
Cont = OneLine[l - 1] == '\\';
if (Cont)
{
OneLine
[l
- 1] = '\0'; KillPostBlanks
(OneLine
); l
= strlen(OneLine
);
}
if (*OneLine != '"') SynError(OneLine);
if (OneLine[l - 1] != '"')
SynError(OneLine);
OneLine[l - 1] = '\0';
strmaxcat(Msg, OneLine + 1, 4095);
}
while (Cont);
for (PRec = TransRecs; PRec->AbbString; PRec++)
strreplace(Msg, PRec->AbbString, PRec->Character, -1, sizeof(Msg));
List
= (PMsgList
) malloc(sizeof(TMsgList
));
List->Next = NULL;
List->Position = z->TotLength;
List->Contents = as_strdup(Msg);
if (!z->Messages) z->Messages = List;
else z->LastMessage->Next = List;
z->LastMessage = List;
z
->TotLength
+= strlen(Msg
) + 1;
}
}
static char *make_sym_name(const char *p_file_name, int include_guard)
{
char *p_ret, *p_run;
const char *p_base;
size_t l;
Boolean no_replace;
p_base
= strrchr(p_file_name
, PATHSEP
);
if (p_base)
p_file_name = p_base + 1;
p_run
= p_ret
= (char*)malloc(!!include_guard
+ l
+ 1);
if (include_guard)
*p_run++ = '_';
for (; *p_file_name; p_file_name++)
{
no_replace = (p_run == p_ret) ? as_isalpha(*p_file_name) : as_isalnum(*p_file_name);
*p_run++ = no_replace
? (include_guard ? as_toupper(*p_file_name) : as_tolower(*p_file_name))
: '_';
}
*p_run++ = '\0';
return p_ret;
}
static void write_dual(const void *p_v_data, size_t data_len)
{
if (p_msg_file)
fwritechk(p_msg_file_name, IO_RETCODE_MSG, p_v_data, 1, data_len, p_msg_file);
if (p_msh_file)
{
const unsigned char *p_data = (const unsigned char*)p_v_data;
size_t z;
for (z = 0; z < data_len; z++)
{
if (!(bytes_written & 15))
{
if (bytes_written > 0)
}
else
fprintf(p_msh_file
, "0x%02x", p_data
[z
]);
bytes_written++;
}
}
else
bytes_written += data_len;
}
static void write_dual_4_le(LongInt *p_lword)
{
if (HostBigEndian)
DSwap(p_lword, 4);
write_dual(p_lword, 4);
if (HostBigEndian)
DSwap(p_lword, 4);
}
/*---------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
char Line[1024], Cmd[1024], *p, Save;
PMsgCat z;
TMsgCat TmpCat;
PMsgList List;
int c, argz, nextidx, curridx;
time_t stamp;
LongInt Id1, Id2;
LongInt RunPos, StrPos;
const char *pSrcName = NULL, *p_rsc_file_name = NULL;
char *p_rsc_file_incl_guard_sym = NULL, *p_msh_file_incl_guard_sym = NULL;
be_le_init(); strutil_init();
curridx = 0;
nextidx = -1;
for (argz = 1; argz < argc; argz++)
{
if (!strcmp(argv
[argz
], "-h"))
nextidx = 2;
else if (!strcmp(argv
[argz
], "-m"))
nextidx = 1;
else if (!strcmp(argv
[argz
], "-i"))
nextidx = 3;
else
{
int thisidx;
if (nextidx >= 0)
{
thisidx = nextidx;
nextidx = -1;
}
else
thisidx = curridx++;
switch (thisidx)
{
case 0:
pSrcName = argv[argz]; break;
case 1:
p_msg_file_name = argv[argz]; break;
case 2:
p_rsc_file_name = argv[argz]; break;
case 3:
p_msh_file_name = argv[argz]; break;
}
}
}
if (!pSrcName)
{
fprintf(stderr
, "usage: %s <input resource file> <[-m] output msg file> <[-i] output include file> [[-h ]header file]\n", *argv
);
}
p_src_file = fopenchk(pSrcName, IO_RETCODE_SRC, "r");
if (p_rsc_file_name)
{
p_rsc_file = fopenchk(p_rsc_file_name, IO_RETCODE_RSC, "w");
p_rsc_file_incl_guard_sym = make_sym_name(p_rsc_file_name, 1);
}
else
p_rsc_file = NULL;
stamp = MyGetFileTime(argv[1]); Id1 = stamp & 0x7fffffff;
Id2 = 0;
for (c
= 0; c
< min
((int)strlen(argv
[1]), 4); c
++)
Id2 = (Id2 << 8) + ((Byte) argv[1][c]);
if (p_rsc_file)
{
fprintf(p_rsc_file
, "#ifndef %s\n", p_rsc_file_incl_guard_sym
);
fprintf(p_rsc_file
, "#define %s\n", p_rsc_file_incl_guard_sym
);
fprintf(p_rsc_file
, "#define MsgId1 %ld\n", (long) Id1
);
fprintf(p_rsc_file
, "#define MsgId2 %ld\n", (long) Id2
);
}
MsgCounter = CatCount = 0; MsgCats = NULL; DefCat = -1;
while (!feof(p_src_file
))
{
GetLine(Line); KillPrefBlanks(Line); KillPostBlanks(Line);
if ((*Line != ';') && (*Line != '#') && (*Line != '\0'))
{
for (p = Line; !as_isspace(*p) && *p; p++);
Save = *p; *p = '\0'; strmaxcpy(Cmd, Line, 1024); *p = Save; strmov(Line, p);
if (!as_strcasecmp(Cmd, "LANGS")) Process_LANGS(Line);
else if (!as_strcasecmp(Cmd, "DEFAULT")) Process_DEFAULT(Line);
else if (!as_strcasecmp(Cmd, "MESSAGE")) Process_MESSAGE(Line);
}
}
if (p_rsc_file)
{
fprintf(p_rsc_file
, "#endif /* #ifndef %s */\n", p_rsc_file_incl_guard_sym
);
free(p_rsc_file_incl_guard_sym
); p_rsc_file_incl_guard_sym
= NULL
;
}
if (p_msg_file_name || p_msh_file_name)
{
if (p_msg_file_name)
p_msg_file = fopenchk(p_msg_file_name, IO_RETCODE_MSG, OPENWRMODE);
if (p_msh_file_name)
{
char *p_array_name = make_sym_name(p_msh_file_name, 0);
p_msh_file = fopenchk(p_msh_file_name, IO_RETCODE_MSH, "w");
p_msh_file_incl_guard_sym = make_sym_name(p_msh_file_name, 1);
fprintf(p_msh_file
, "#ifndef %s\n", p_msh_file_incl_guard_sym
);
fprintf(p_msh_file
, "#define %s\n", p_msh_file_incl_guard_sym
);
fprintf(p_msh_file
, "static const unsigned char %s_data[] = {", p_array_name
);
free(p_array_name
); p_array_name
= NULL
;
}
bytes_written = 0;
/* Magic-String */
write_dual
(IdentString
, strlen(IdentString
));
write_dual_4_le(&Id1); write_dual_4_le(&Id2);
/* Default nach vorne */
if (DefCat > 0)
{
TmpCat = MsgCats[0]; MsgCats[0] = MsgCats[DefCat]; MsgCats[DefCat] = TmpCat;
}
/* Startadressen String-Kataloge berechnen */
RunPos = bytes_written + 1;
for (z = MsgCats; z < MsgCats + CatCount; z++)
RunPos
+= (z
->HeadLength
= strlen(z
->CtryName
) + 1 + 4 + 4 + (4 * z
->CtryCodeCnt
) + 4);
for (z = MsgCats; z < MsgCats + CatCount; z++)
{
z->FilePos = RunPos; RunPos += z->TotLength + (4 * MsgCounter);
}
/* Country-Records schreiben */
for (z = MsgCats; z < MsgCats + CatCount; z++)
{
write_dual
(z
->CtryName
, strlen(z
->CtryName
) + 1);
write_dual_4_le(&(z->TotLength));
write_dual_4_le(&(z->CtryCodeCnt));
for (c = 0; c < z->CtryCodeCnt; c++) write_dual_4_le(z->CtryCodes + c);
write_dual_4_le(&(z->FilePos));
}
Save = '\0'; write_dual(&Save, 1);
/* Stringtabellen schreiben */
for (z = MsgCats; z < MsgCats + CatCount; z++)
{
for (List = z->Messages; List; List = List->Next)
{
StrPos = z->FilePos + (4 * MsgCounter) + List->Position;
write_dual_4_le(&StrPos);
}
for (List = z->Messages; List; List = List->Next)
write_dual
(List
->Contents
, strlen(List
->Contents
) + 1);
}
/* faeaedisch... */
if (p_msg_file)
{
fclose(p_msg_file
); p_msg_file
= NULL
;
}
if (p_msh_file)
{
fprintf(p_msh_file
, "#endif /* %s */\n", p_msh_file_incl_guard_sym
);
free(p_msh_file_incl_guard_sym
); p_msh_file_incl_guard_sym
= NULL
;
}
}
return 0;
}
#ifdef CKMALLOC
#undef malloc
#undef realloc
void *ckmalloc(size_t s)
{
if (!tmp)
{
fprintf(stderr
, "allocation error(malloc): out of memory");
}
return tmp;
}
void *ckrealloc(void *p, size_t s)
{
if (!tmp)
{
fprintf(stderr
, "allocation error(realloc): out of memory");
}
return tmp;
}
#endif