Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* rescomp.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Compiler fuer Message-Dateien                                             */
  8. /*                                                                           */
  9. /*    17. 5.1998  Symbol gegen Mehrfachinklusion eingebaut                   */
  10. /*     5. 7.1998  zusaetzliche Sonderzeichen                                 */
  11. /*                                                                           */
  12. /*****************************************************************************/
  13.  
  14. #include "stdinc.h"
  15. #include <string.h>
  16. #include <ctype.h>
  17.  
  18. #include "be_le.h"
  19. #include "strutil.h"
  20. #include "bpemu.h"
  21.  
  22. /*****************************************************************************/
  23.  
  24. typedef struct _TMsgList
  25. {
  26.   struct _TMsgList *Next;
  27.   LongInt Position;
  28.   char *Contents;
  29. } TMsgList,*PMsgList;
  30.  
  31. typedef struct
  32. {
  33.   PMsgList Messages,LastMessage;
  34.   char *CtryName;
  35.   LongInt *CtryCodes,CtryCodeCnt;
  36.   LongInt FilePos,HeadLength,TotLength;
  37. } TMsgCat,*PMsgCat;
  38.  
  39. typedef struct
  40. {
  41.   char *AbbString,*Character;
  42. } TransRec;
  43.  
  44. #define IO_RETCODE_SRC 2
  45. #define IO_RETCODE_RSC 3
  46. #define IO_RETCODE_MSG 4
  47. #define IO_RETCODE_MSH 5
  48.  
  49. /*****************************************************************************/
  50.  
  51. #ifdef __TURBOC__
  52. unsigned _stklen = 16384;
  53. #endif
  54.  
  55. static char *IdentString = "AS Message Catalog - not readable\n\032\004";
  56.  
  57. static LongInt MsgCounter;
  58. static PMsgCat MsgCats;
  59. static LongInt CatCount, DefCat;
  60. static const char *p_msg_file_name = NULL, *p_msh_file_name = NULL;
  61. static FILE *p_src_file, *p_msg_file, *p_rsc_file, *p_msh_file;
  62. static size_t bytes_written;
  63.  
  64. static TransRec TransRecs[] =
  65. {
  66.   { "\\n"     , "\n"      },
  67.   { NULL      , NULL      }
  68. };
  69.  
  70. /*****************************************************************************/
  71.  
  72. typedef struct _TIncList
  73. {
  74.   struct _TIncList *Next;
  75.   FILE *Contents;
  76. } TIncList,*PIncList;
  77.  
  78. PIncList IncList = NULL;
  79.  
  80. void WrError(Word Num)
  81. {
  82.   (void)Num;
  83. }
  84.  
  85. static void fwritechk(const char *pArg, int retcode,
  86.                       const void *pBuffer, size_t size, size_t nmemb, FILE *pFile)
  87. {
  88.   size_t res;
  89.  
  90.   res = fwrite(pBuffer, size, nmemb, pFile);
  91.   if (res != nmemb)
  92.   {
  93.     perror(pArg);
  94.     exit(retcode);
  95.   }
  96. }
  97.  
  98. static FILE *fopenchk(const char *pName, int retcode, const char *pOpenMode)
  99. {
  100.   FILE *pRes;
  101.  
  102.   pRes = fopen(pName, pOpenMode);
  103.   if (!pRes)
  104.   {
  105.     perror(pName);
  106.     exit(retcode);
  107.   }
  108.   return pRes;
  109. }
  110.  
  111. static void GetLine(char *Dest)
  112. {
  113.   PIncList OneFile;
  114.  
  115.   ReadLn(p_src_file, Dest);
  116.   if (!as_strncasecmp(Dest, "INCLUDE", 7))
  117.   {
  118.     OneFile = (PIncList) malloc(sizeof(TIncList));
  119.     OneFile->Next = IncList; OneFile->Contents = p_src_file;
  120.     IncList = OneFile;
  121.     strmov(Dest, Dest + 7); KillPrefBlanks(Dest); KillPrefBlanks(Dest);
  122.     p_src_file = fopenchk(Dest, 2, "r");
  123.     GetLine(Dest);
  124.   }
  125.   if (feof(p_src_file) && IncList)
  126.   {
  127.     fclose(p_src_file);
  128.     OneFile = IncList; IncList = OneFile->Next;
  129.     p_src_file = OneFile->Contents; free(OneFile);
  130.   }
  131. }
  132.  
  133. /*****************************************************************************/
  134.  
  135. static void SynError(char *LinePart)
  136. {
  137.   fprintf(stderr, "syntax error : %s\n", LinePart); exit(10);
  138. }
  139.  
  140. /*---------------------------------------------------------------------------*/
  141.  
  142. static void Process_LANGS(char *Line)
  143. {
  144.   char NLine[1024], *p, *p2, *p3, *end, z, Part[1024];
  145.   PMsgCat PCat;
  146.   int num;
  147.  
  148.   strmaxcpy(NLine, Line, 1024);
  149.   KillPrefBlanks(NLine); KillPostBlanks(NLine);
  150.  
  151.   p = NLine; z = 0;
  152.   while (*p)
  153.   {
  154.     for (; *p && !as_isspace(*p); p++);
  155.     for (; *p && as_isspace(*p); p++);
  156.     z++;
  157.   }
  158.  
  159.   MsgCats = (PMsgCat) malloc(sizeof(TMsgCat) * (CatCount = z)); p = NLine;
  160.   for (z = 0, PCat = MsgCats; z < CatCount; z++, PCat++)
  161.   {
  162.     PCat->Messages = NULL;
  163.     PCat->TotLength = 0;
  164.     PCat->CtryCodeCnt = 0;
  165.     for (p2 = p; *p2 && !as_isspace(*p2); p2++);
  166.     if (*p2 == '\0')
  167.       strcpy(Part, p);
  168.     else
  169.     {
  170.       *p2 = '\0'; strcpy(Part, p);
  171.       for (p = p2 + 1; *p && as_isspace(*p2); p++); /* TODO: p instead of p2? */
  172.     }
  173.     if ((!*Part) || (Part[strlen(Part)-1] != ')')) SynError(Part);
  174.     Part[strlen(Part) - 1] = '\0';
  175.     p2 = strchr(Part, '(');
  176.     if (!p2)
  177.       SynError(Part);
  178.     *p2 = '\0';
  179.     PCat->CtryName = as_strdup(Part); p2++;
  180.     do
  181.     {
  182.       for (p3 = p2; ((*p3) && (*p3 != ',')); p3++);
  183.       switch (*p3)
  184.       {
  185.         case '\0':
  186.           num = strtol(p2, &end, 10); p2 = p3;
  187.           break;
  188.         case ',':
  189.           *p3 = '\0'; num = strtol(p2, &end, 10); p2 = p3 + 1;
  190.           break;
  191.         default:
  192.           num = 0;
  193.           break;
  194.       }
  195.       if (*end) SynError("numeric format");
  196.       PCat->CtryCodes=(PCat->CtryCodeCnt == 0) ?
  197.                       (LongInt *) malloc(sizeof(LongInt)) :
  198.                       (LongInt *) realloc(PCat->CtryCodes, sizeof(LongInt) * (PCat->CtryCodeCnt + 1));
  199.       PCat->CtryCodes[PCat->CtryCodeCnt++] = num;
  200.     }
  201.     while (*p2!='\0');
  202.   }
  203. }
  204.  
  205. static void Process_DEFAULT(char *Line)
  206. {
  207.   PMsgCat z;
  208.  
  209.   if (!CatCount) SynError("DEFAULT before LANGS");
  210.   KillPrefBlanks(Line); KillPostBlanks(Line);
  211.   for (z = MsgCats; z < MsgCats + CatCount; z++)
  212.     if (!as_strcasecmp(z->CtryName,Line))
  213.       break;
  214.   if (z >= MsgCats + CatCount)
  215.     SynError("unknown country name in DEFAULT");
  216.   DefCat = z - MsgCats;
  217. }
  218.  
  219. static void Process_MESSAGE(char *Line)
  220. {
  221.   char Msg[4096];
  222.   String OneLine;
  223.   int l;
  224.   PMsgCat z;
  225.   TransRec *PRec;
  226.   PMsgList List;
  227.   Boolean Cont;
  228.  
  229.   KillPrefBlanks(Line); KillPostBlanks(Line);
  230.   if (p_rsc_file) fprintf(p_rsc_file, "#define Num_%s %d\n", Line, MsgCounter);
  231.   MsgCounter++;
  232.  
  233.   for (z = MsgCats; z < MsgCats + CatCount; z++)
  234.   {
  235.     *Msg = '\0';
  236.     do
  237.     {
  238.       GetLine(OneLine); KillPrefBlanks(OneLine); KillPostBlanks(OneLine);
  239.       l = strlen(OneLine);
  240.       Cont = OneLine[l - 1] == '\\';
  241.       if (Cont)
  242.       {
  243.         OneLine[l - 1] = '\0'; KillPostBlanks(OneLine); l = strlen(OneLine);
  244.       }
  245.       if (*OneLine != '"') SynError(OneLine);
  246.       if (OneLine[l - 1] != '"')
  247.         SynError(OneLine);
  248.       OneLine[l - 1] = '\0';
  249.       strmaxcat(Msg, OneLine + 1, 4095);
  250.     }
  251.     while (Cont);
  252.     for (PRec = TransRecs; PRec->AbbString; PRec++)
  253.       strreplace(Msg, PRec->AbbString, PRec->Character, -1, sizeof(Msg));
  254.     List = (PMsgList) malloc(sizeof(TMsgList));
  255.     List->Next = NULL;
  256.     List->Position = z->TotLength;
  257.     List->Contents = as_strdup(Msg);
  258.     if (!z->Messages) z->Messages = List;
  259.     else z->LastMessage->Next = List;
  260.     z->LastMessage = List;
  261.     z->TotLength += strlen(Msg) + 1;
  262.   }
  263. }
  264.  
  265. static char *make_sym_name(const char *p_file_name, int include_guard)
  266. {
  267.   char *p_ret, *p_run;
  268.   const char *p_base;
  269.   size_t l;
  270.   Boolean no_replace;
  271.  
  272.   p_base = strrchr(p_file_name, PATHSEP);
  273.   if (p_base)
  274.     p_file_name = p_base + 1;
  275.   l = strlen(p_file_name);
  276.   p_run = p_ret = (char*)malloc(!!include_guard + l + 1);
  277.   if (include_guard)
  278.     *p_run++ = '_';
  279.   for (; *p_file_name; p_file_name++)
  280.   {
  281.     no_replace = (p_run == p_ret) ? as_isalpha(*p_file_name) : as_isalnum(*p_file_name);
  282.     *p_run++ = no_replace
  283.              ? (include_guard ? as_toupper(*p_file_name) : as_tolower(*p_file_name))
  284.              : '_';
  285.   }
  286.   *p_run++ = '\0';
  287.   return p_ret;
  288. }
  289.  
  290. static void write_dual(const void *p_v_data, size_t data_len)
  291. {
  292.   if (p_msg_file)
  293.     fwritechk(p_msg_file_name, IO_RETCODE_MSG, p_v_data, 1, data_len, p_msg_file);
  294.  
  295.   if (p_msh_file)
  296.   {
  297.     const unsigned char *p_data = (const unsigned char*)p_v_data;
  298.     size_t z;
  299.  
  300.     for (z = 0; z < data_len; z++)
  301.     {
  302.       if (!(bytes_written & 15))
  303.       {
  304.         if (bytes_written > 0)
  305.           fprintf(p_msh_file, ",");
  306.         fprintf(p_msh_file, "\n  ");
  307.       }
  308.       else
  309.         fprintf(p_msh_file, ",");
  310.       fprintf(p_msh_file, "0x%02x", p_data[z]);
  311.       bytes_written++;
  312.     }
  313.   }
  314.   else
  315.     bytes_written += data_len;
  316. }
  317.  
  318. static void write_dual_4_le(LongInt *p_lword)
  319. {
  320.   if (HostBigEndian)
  321.     DSwap(p_lword, 4);
  322.   write_dual(p_lword, 4);
  323.   if (HostBigEndian)
  324.     DSwap(p_lword, 4);
  325. }
  326.  
  327. /*---------------------------------------------------------------------------*/
  328.  
  329. int main(int argc, char **argv)
  330. {
  331.   char Line[1024], Cmd[1024], *p, Save;
  332.   PMsgCat z;
  333.   TMsgCat TmpCat;
  334.   PMsgList List;
  335.   int c, argz, nextidx, curridx;
  336.   time_t stamp;
  337.   LongInt Id1, Id2;
  338.   LongInt RunPos, StrPos;
  339.   const char *pSrcName = NULL, *p_rsc_file_name = NULL;
  340.   char *p_rsc_file_incl_guard_sym = NULL, *p_msh_file_incl_guard_sym = NULL;
  341.  
  342.   be_le_init(); strutil_init();
  343.  
  344.   curridx = 0;
  345.   nextidx = -1;
  346.   for (argz = 1; argz < argc; argz++)
  347.   {
  348.     if (!strcmp(argv[argz], "-h"))
  349.       nextidx = 2;
  350.     else if (!strcmp(argv[argz], "-m"))
  351.       nextidx = 1;
  352.     else if (!strcmp(argv[argz], "-i"))
  353.       nextidx = 3;
  354.     else
  355.     {
  356.       int thisidx;
  357.  
  358.       if (nextidx >= 0)
  359.       {
  360.         thisidx = nextidx;
  361.         nextidx = -1;
  362.       }
  363.       else
  364.         thisidx = curridx++;
  365.       switch (thisidx)
  366.       {
  367.         case 0:
  368.           pSrcName = argv[argz]; break;
  369.         case 1:
  370.           p_msg_file_name = argv[argz]; break;
  371.         case 2:
  372.           p_rsc_file_name = argv[argz]; break;
  373.         case 3:
  374.           p_msh_file_name = argv[argz]; break;
  375.       }
  376.     }
  377.   }
  378.  
  379.   if (!pSrcName)
  380.   {
  381.     fprintf(stderr, "usage: %s <input resource file> <[-m] output msg file> <[-i] output include file> [[-h ]header file]\n", *argv);
  382.     exit(1);
  383.   }
  384.  
  385.   p_src_file = fopenchk(pSrcName, IO_RETCODE_SRC, "r");
  386.  
  387.   if (p_rsc_file_name)
  388.   {
  389.     p_rsc_file = fopenchk(p_rsc_file_name, IO_RETCODE_RSC, "w");
  390.     p_rsc_file_incl_guard_sym = make_sym_name(p_rsc_file_name, 1);
  391.   }
  392.   else
  393.     p_rsc_file = NULL;
  394.  
  395.   stamp = MyGetFileTime(argv[1]); Id1 = stamp & 0x7fffffff;
  396.   Id2 = 0;
  397.   for (c = 0; c < min((int)strlen(argv[1]), 4); c++)
  398.    Id2 = (Id2 << 8) + ((Byte) argv[1][c]);
  399.   if (p_rsc_file)
  400.   {
  401.     fprintf(p_rsc_file, "#ifndef %s\n", p_rsc_file_incl_guard_sym);
  402.     fprintf(p_rsc_file, "#define %s\n", p_rsc_file_incl_guard_sym);
  403.     fprintf(p_rsc_file, "#define MsgId1 %ld\n", (long) Id1);
  404.     fprintf(p_rsc_file, "#define MsgId2 %ld\n", (long) Id2);
  405.   }
  406.  
  407.   MsgCounter = CatCount = 0; MsgCats = NULL; DefCat = -1;
  408.   while (!feof(p_src_file))
  409.   {
  410.     GetLine(Line); KillPrefBlanks(Line); KillPostBlanks(Line);
  411.     if ((*Line != ';') && (*Line != '#') && (*Line != '\0'))
  412.     {
  413.       for (p = Line; !as_isspace(*p) && *p; p++);
  414.       Save = *p; *p = '\0'; strmaxcpy(Cmd, Line, 1024); *p = Save; strmov(Line, p);
  415.       if (!as_strcasecmp(Cmd, "LANGS")) Process_LANGS(Line);
  416.       else if (!as_strcasecmp(Cmd, "DEFAULT")) Process_DEFAULT(Line);
  417.       else if (!as_strcasecmp(Cmd, "MESSAGE")) Process_MESSAGE(Line);
  418.     }
  419.   }
  420.   fclose(p_src_file);
  421.  
  422.   if (p_rsc_file)
  423.   {
  424.     fprintf(p_rsc_file, "#endif /* #ifndef %s */\n", p_rsc_file_incl_guard_sym);
  425.     free(p_rsc_file_incl_guard_sym); p_rsc_file_incl_guard_sym = NULL;
  426.     fclose(p_rsc_file);
  427.   }
  428.  
  429.   if (p_msg_file_name || p_msh_file_name)
  430.   {
  431.     if (p_msg_file_name)
  432.       p_msg_file = fopenchk(p_msg_file_name, IO_RETCODE_MSG, OPENWRMODE);
  433.     if (p_msh_file_name)
  434.     {
  435.       char *p_array_name = make_sym_name(p_msh_file_name, 0);
  436.  
  437.       p_msh_file = fopenchk(p_msh_file_name, IO_RETCODE_MSH, "w");
  438.       p_msh_file_incl_guard_sym = make_sym_name(p_msh_file_name, 1);
  439.       fprintf(p_msh_file, "#ifndef %s\n", p_msh_file_incl_guard_sym);
  440.       fprintf(p_msh_file, "#define %s\n", p_msh_file_incl_guard_sym);
  441.       fprintf(p_msh_file, "static const unsigned char %s_data[] = {", p_array_name);
  442.       free(p_array_name); p_array_name = NULL;
  443.     }
  444.     bytes_written = 0;
  445.  
  446.     /* Magic-String */
  447.  
  448.     write_dual(IdentString, strlen(IdentString));
  449.     write_dual_4_le(&Id1); write_dual_4_le(&Id2);
  450.  
  451.     /* Default nach vorne */
  452.  
  453.     if (DefCat > 0)
  454.     {
  455.       TmpCat = MsgCats[0]; MsgCats[0] = MsgCats[DefCat]; MsgCats[DefCat] = TmpCat;
  456.     }
  457.  
  458.     /* Startadressen String-Kataloge berechnen */
  459.  
  460.     RunPos = bytes_written + 1;
  461.     for (z = MsgCats; z < MsgCats + CatCount; z++)
  462.       RunPos += (z->HeadLength = strlen(z->CtryName) + 1 + 4 + 4 + (4 * z->CtryCodeCnt) + 4);
  463.     for (z = MsgCats; z < MsgCats + CatCount; z++)
  464.     {
  465.       z->FilePos = RunPos; RunPos += z->TotLength + (4 * MsgCounter);
  466.     }
  467.  
  468.     /* Country-Records schreiben */
  469.  
  470.     for (z = MsgCats; z < MsgCats + CatCount; z++)
  471.     {
  472.       write_dual(z->CtryName, strlen(z->CtryName) + 1);
  473.       write_dual_4_le(&(z->TotLength));
  474.       write_dual_4_le(&(z->CtryCodeCnt));
  475.       for (c = 0; c < z->CtryCodeCnt; c++) write_dual_4_le(z->CtryCodes + c);
  476.       write_dual_4_le(&(z->FilePos));
  477.     }
  478.     Save = '\0'; write_dual(&Save, 1);
  479.  
  480.     /* Stringtabellen schreiben */
  481.  
  482.     for (z = MsgCats; z < MsgCats + CatCount; z++)
  483.     {
  484.       for (List = z->Messages; List; List = List->Next)
  485.       {
  486.         StrPos = z->FilePos + (4 * MsgCounter) + List->Position;
  487.         write_dual_4_le(&StrPos);
  488.       }
  489.       for (List = z->Messages; List; List = List->Next)
  490.         write_dual(List->Contents, strlen(List->Contents) + 1);
  491.     }
  492.  
  493.     /* faeaedisch... */
  494.  
  495.     if (p_msg_file)
  496.     {
  497.       fclose(p_msg_file); p_msg_file = NULL;
  498.     }
  499.     if (p_msh_file)
  500.     {
  501.       fprintf(p_msh_file, "\n};\n");
  502.       fprintf(p_msh_file, "#endif /* %s */\n", p_msh_file_incl_guard_sym);
  503.       free(p_msh_file_incl_guard_sym); p_msh_file_incl_guard_sym = NULL;
  504.       fclose(p_msh_file);
  505.     }
  506.  
  507.   }
  508.  
  509.   return 0;
  510. }
  511.  
  512. #ifdef CKMALLOC
  513. #undef malloc
  514. #undef realloc
  515.  
  516. void *ckmalloc(size_t s)
  517. {
  518.   void *tmp = malloc(s);
  519.  
  520.   if (!tmp)
  521.   {
  522.     fprintf(stderr, "allocation error(malloc): out of memory");
  523.     exit(255);
  524.   }
  525.   return tmp;
  526. }
  527.  
  528. void *ckrealloc(void *p, size_t s)
  529. {
  530.   void *tmp = realloc(p, s);
  531.   if (!tmp)
  532.   {
  533.     fprintf(stderr, "allocation error(realloc): out of memory");
  534.     exit(255);
  535.   }
  536.   return tmp;
  537. }
  538. #endif
  539.