⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msgbind.c

📁 arj source code
💻 C
字号:
/* * $Id: msgbind.c,v 1.4 2003/06/22 11:12:28 andrew_belov Exp $ * --------------------------------------------------------------------------- * This file creates the  message files  for all ARJ modules. It  is essential * that it does not make use of any  ARJ modules (MISC.C and so on) because it * is the first file of the project. * *//* We need to manually include the needed files because ARJ.H may contain   references to missing message header files */#include "environ.h"#include "defines.h"#include "filemode.h"#include "misc.h"#include "crc32.h"#include "arjdata.h"#include <ctype.h>#include <signal.h>#include <time.h>#define MSG_SIZE               32752    /* Constant msg buffer size */#define POOL_SIZE              51200    /* Maximum size of variable-len buf */#define POOL_R_INC              1024    /* Realloc incrementation */#define COLUMNS                   79    /* Columns per line in I*.* */static char msgpool[32];       /* {MSGPOOL} or {HARDERR}   */static char msgname[40];       /* {MSG_OUT_OF_MEM} */static char targets[128];      /* {ARJ, ARJSFXV, ARJSFXJR} */static char systems[128];      /* {DOS, OS2, WIN32, UNIX} */static char bindings[16];      /* {S, C, or none (means ANY} */static char locales[32];       /* {en, ru} */static char msgtype[8];        /* {N} or {F}, for NMSG/FMSG, respectively */static char rdir[FILENAME_MAX];/* Resource directory */static char M_FMSG[]="FMSG";static char M_NMSG[]="char";static char INCL[]="#include \"bindings.h\"\n#include \"environ.h\"\n#include \"arjtypes.h\"\n\n";static char SKIP[]="NULL";struct pool{ char name[32]; unsigned int msgs; char *data; char st_class; unsigned int safesize; unsigned int columns; unsigned int indent; unsigned long crc32;};/* A Q&D emulation of the strupr() and strlwr() for those who don't have it */#ifndef HAVE_STRLWRstatic char *strlwr(char *str){ char *p; for(p=str; *p!='\0'; p++)  *p=tolower(*p); return(str);}#endif#ifndef HAVE_STRUPRstatic char *strupr(char *str){ char *p; for(p=str; *p!='\0'; p++)  *p=toupper(*p); return(str);}#endif/* Remove given characters */char *compress(char *i, char f){ int c, d; for(c=d=0; i[c]!='\0'; c++) {  if(i[c]!=f)   i[d++]=i[c]; } i[d]='\0'; return(i);}/* Strip all leading spaces */char *ltrim(char *i){ if (i!=NULL) {  unsigned int c, j;  for (c=0; i[c]==' '||i[c]=='\x9'; c++);  if (i[c]!=(char)0)  {   for (j=0; i[c]!='\0'; j++)   {    i[j]=i[c]; c++;   }   i[j]=(char)0;  } } return i;}/* Strip all trailing spaces */char *rtrim(char *i){ if (i!=NULL) {  unsigned int c, j;  j=0;  for (c=0; i[c]!='\0'; c++) if (i[c]!=' '&&i[c]!='\x9') j=c+1;  i[j]='\0'; } return i;}/* Transform "\n", "\r", "\a" and "\b" characters to the corresponding ASCII   equivalents */void patch_string(char *i){ int c, j; if (i!=NULL) {  for(c=0; i[c]!='\0'; c++)  {   if(i[c]=='\\')   {    switch(i[c+1])    {     case 'a':      i[c]='\a';      break;     case 'b':      i[c]='\b';      break;     case 'f':      i[c]='\f';      break;     case 'n':      i[c]='\n';      break;     case 'r':      i[c]='\r';      break;     case 't':      i[c]='\t';      break;     case 'v':      i[c]='\v';      break;     case '\"':      i[c]='\"';      break;     case '\\':      i[c]='\\';      break;    }    for(j=c+1; i[j]!='\0'; j++)     i[j]=i[j+1];   }  } }}/* Get one phrase in brackets */char *read_brackets(FILE *file, char *buf, int size, int keep){ int c, offset; /* Until the left one has been met... */ while((c=fgetc(file))!=(int)'{')  if(c==-1) return(NULL); /* Now fill the buffer */ if(keep) {  offset=1;  buf[0]='{'; } else  offset=0; while((c=fgetc(file))!=(int)'}') {  if(c==-1) return(NULL);  if(offset<size-1-keep) buf[offset++]=(char)c; } if(keep)  buf[offset++]='}'; buf[offset]='\0'; return(ltrim(rtrim(buf)));}/* Checks if the given parameter is present in the bracketed list. Returns   parameter number (1...32767) or 0 => the parameter was not found. */int is_in_brackets(char *brackets, char *param){ const char *delimiters="{, ;}"; int j, firstpos=1, inspace=0, count=0; int invert=0; for(j=1; brackets[j]!='\0'; j++) {  while(brackets[firstpos]=='!')  {   invert=!invert;   firstpos++;  }  if(strchr(delimiters, brackets[j])!=NULL&&!inspace)  {   count++;   inspace=1;   if(memcmp(brackets+firstpos, param, j-firstpos)==0||brackets[firstpos]=='*')    return(invert?0:count);  }  else if(strchr(delimiters, brackets[j])==NULL&&inspace)  {   inspace=0;   firstpos=j;  } } return(invert);}/* Fetch a quoted message from the brackets. The index given varies from 1   to 32767. */char *fetch_quotes(FILE *resfile, int index, char *buf, int size){ int c, tc, offset, qcount=0, quoted=0; FILE *tstream; char t_name[FILENAME_MAX]; int t_offset; /* Until the left one has been met... */ while((c=fgetc(resfile))!=(int)'{')  if(c==EOF)   return(NULL); /* Now wait until we come to the closing bracket, or... */ offset=0; while((c=fgetc(resfile))!=(int)'}') {  if(c==EOF)   return(NULL);  /* Reference to external file (v 1.30+) */  else if(c=='@'&&!quoted&&qcount%2==0)  {   qcount+=2;   if(qcount==index*2)   {    strcpy(t_name, rdir);    t_offset=strlen(t_name);    while((tc=fgetc(resfile))!=EOF&&(isalnum(tc)||tc=='.'||tc=='_'||tc=='\\'||tc=='/'))     t_name[t_offset++]=tc;    t_name[t_offset]='\0';    if((tstream=fopen(t_name, m_r))==NULL)     printf("Malformed declaration: <%s>\n", t_name);    else    {     buf[offset++]='\"';     while((tc=fgetc(tstream))!=EOF)     {      switch(tc)      {       case '\n':        buf[offset++]='\\';        buf[offset++]='n';        break;       case '\a':        buf[offset++]='\\';        buf[offset++]='a';        break;       case '\b':        buf[offset++]='\\';        buf[offset++]='b';        break;       case '\"':        buf[offset++]='\\';        buf[offset++]='\"';        break;       case '\\':        buf[offset++]='\\';        buf[offset++]='\\';        break;       default:        buf[offset++]=tc;      }     }     buf[offset++]='\"';     buf[offset]='\0';     fclose(tstream);     return(buf);    }   }  }  else if(c=='\"'&&!quoted)  {   if(++qcount==index*2)   {    buf[offset++]='\"';    buf[offset]='\0';    return(buf);   }  }  quoted=c=='\\';  if(offset<size-1&&qcount==index*2-1)   buf[offset++]=(char)c; } return(NULL);}/* Fetch messages from the resource file, return NULL if EOF. */char *get_msg(FILE *resfile, char *target, char *c_system, char binding, char *locale, char *buf, int size){ int locale_offset; while(!feof(resfile)) {  if(read_brackets(resfile, msgpool, sizeof(msgpool), 0)==NULL||     read_brackets(resfile, msgname, sizeof(msgname), 0)==NULL||     read_brackets(resfile, targets, sizeof(targets), 1)==NULL||     read_brackets(resfile, systems, sizeof(systems), 1)==NULL||     read_brackets(resfile, bindings, sizeof(bindings), 0)==NULL||     read_brackets(resfile, locales, sizeof(locales), 1)==NULL||     read_brackets(resfile, msgtype, sizeof(msgtype), 0)==NULL)   return(NULL);  strlwr(targets);  strlwr(systems);  strlwr(bindings);  strlwr(locales);  strupr(msgtype);  locale_offset=is_in_brackets(locales, locale);  if(is_in_brackets(targets, target)&&is_in_brackets(systems, c_system)&&(bindings[0]=='\0'||strchr(bindings, binding)!=NULL)&&locale_offset)  {   if(fetch_quotes(resfile, locale_offset, buf, size)!=NULL)    return(buf);  }  else   read_brackets(resfile, buf, 0, 0); } return(NULL);}/* malloc */void *malloc_msg(unsigned int size){ void *p; if((p=malloc(size))==NULL) {  printf("Out of memory!\r\n");  exit(4); } return(p);}/* Add header to file */void put_hdr(FILE *file, char *name, char *src){ char buf[FILENAME_MAX]; time_t cur_unixtime; struct tm *stm; cur_unixtime=time(NULL); stm=localtime(&cur_unixtime); strcpyn(buf, name, sizeof(buf)); strupr(buf); fprintf(file, "/*\n"          " * %-29s, %04u/%02u/%02u\n"          " * ---------------------------------------------------------------------------\n"          " * Do not modify this file. It is automatically generated from by MSGBIND from\n"          " * %s.\n"          " * To rebuild the language resources, run MSGBIND.\n"          " *\n"          " */\n\n", buf, (unsigned int)stm->tm_year+1900, stm->tm_mon+1, stm->tm_mday, strupr(src));}/* And so we begin... */int main(int argc, char **argv){ char source[FILENAME_MAX];             /* ReSource filename */ char target_i[FILENAME_MAX];           /* .C-file containing pointers */ char target_n[FILENAME_MAX];           /* All NMSGs */ char target_f[FILENAME_MAX];           /* All FMSGs */ char target_h[FILENAME_MAX];           /* Include file - all NMSGs/FMSGs */ char target[FILENAME_MAX], locale[15]; char c_system[32]; char binding; char *msg_buffer;                      /* Messages may be large enough... */ struct pool pool[32];                  /* Up to 32 separate msg arrays */ int tpool, cur_pool=0, i; int buf_len; FILE *resfile, *ifile, *nfile, *ffile, *hfile; char pathsep[2]; printf("MSGBIND v 1.65  [14/12/2002]  Not a part of any binary package!\n\n"); if(argc<6) {  printf("Usage: MSGBIND <resource> <target> <OS> <binding> <locale> [target directory],\n"         "       e.g, to build MSG_SFXV.*, type MSGBIND MSG.RES MSG_SFXV DOS en\n"         "\n"         "The target directory is optional. If specified (e.g., BINARIES\\ENGLISH), all\n"         "compiled .C files will be placed there.\n");  exit(1); } msg_buffer=(char *)malloc_msg(MSG_SIZE); build_crc32_table(); pathsep[0]=PATHSEP_DEFAULT; pathsep[1]='\0'; strcpyn(source, argv[1], sizeof(source)-8); /* Fix for GCC/EMX: convert UNIX-like representations to DOS */#if PATHSEP_UNIX!=PATHSEP_DEFAULT for(i=0; source[i]!='\0'; i++)  if(source[i]==PATHSEP_UNIX)   source[i]=PATHSEP_DEFAULT;#endif if(strrchr(source, PATHSEP_DEFAULT)==NULL)  rdir[0]='\0'; else {  strcpy(rdir, source);  strrchr(rdir, PATHSEP_DEFAULT)[1]='\0'; } strcpyn(target, argv[2], sizeof(target)-8); strcpyn(c_system, argv[3], sizeof(c_system)); binding=tolower(argv[4][0]); /* Beginning with v 1.21, target directory may be also specified */ if(argc==7) {  strcpyn(target_i, argv[6], sizeof(target_i)-8);  strcpyn(target_n, argv[6], sizeof(target_n)-8);  strcpyn(target_f, argv[6], sizeof(target_f)-8);  strcpyn(target_h, argv[6], sizeof(target_f)-8); /* v 1.41+ */  if(argv[6][strlen(argv[6])-1]!=PATHSEP_DEFAULT);  {   strcat(target_i, pathsep);   strcat(target_n, pathsep);   strcat(target_f, pathsep);   strcat(target_h, pathsep);  } } else {  target_i[0]='\0';  target_n[0]='\0';  target_f[0]='\0';  target_h[0]='\0'; } strcat(target_i, "i"); strcat(target_n, "n"); strcat(target_f, "f"); strcat(target_i, argv[2]); strcat(target_n, argv[2]); strcat(target_f, argv[2]); strcat(target_h, argv[2]); /* The source has the extension .MSG, the targets are .H and .C */ if(strchr(source, '.')==NULL)  strcat(source, ".msg"); strcat(target_i, ".c"); strcat(target_n, ".c"); strcat(target_f, ".c"); strcat(target_h, ".h"); strcpyn(locale, argv[5], sizeof(locale)); strlwr(target); strlwr(c_system); strlwr(locale); /* Block out all signals, since this transaction is mission-critical */ signal(SIGINT, SIG_IGN); #ifndef NO_TERM_HDL  signal(SIGTERM, SIG_IGN); #endif if((resfile=fopen(source, m_r))==NULL) {  printf("Can't open source file!\n");  exit(2); } if((ifile=fopen(target_i, m_w))==NULL) {  printf("Can't open index file!\n");  exit(3); } if((nfile=fopen(target_n, m_w))==NULL) {  printf("Can't open NMSG output file!\n");  exit(3); } if((ffile=fopen(target_f, m_w))==NULL) {  printf("Can't open FMSG output file!\n");  exit(3); } if((hfile=fopen(target_h, m_w))==NULL) {  printf("Can't open .h output file!\n");  exit(3); } put_hdr(ifile, target_i, source); put_hdr(nfile, target_n, source); put_hdr(ffile, target_f, source); put_hdr(hfile, target_h, source); fputs(INCL, ifile); fputs(INCL, nfile); fputs(INCL, ffile); fprintf(ifile, "#include \""); for(i=0; target_h[i]!='\0'; i++)  fputc(target_h[i]=='\\'?'/':target_h[i], ifile); fprintf(ifile, "\"\n\n", target_h); /* Ack. Now process the source file line by line... */ while(get_msg(resfile, target, c_system, binding, locale, msg_buffer, MSG_SIZE)!=NULL) {  expand_tags(msg_buffer, MSG_SIZE);  fprintf(toupper(msgtype[0])=='N'?nfile:ffile, "char %s[]=%s;\n", msgname, msg_buffer);  fprintf(hfile, "extern %s %s[];\n", toupper(msgtype[0])=='N'?M_NMSG:M_FMSG, msgname, msg_buffer);  /* Check if the message belongs to a pre-defined message pool */  if(strcmp(msgpool, SKIP))  {   /* Pick a message heap */   for(tpool=0; tpool<cur_pool; tpool++)   {    if(!strcmp(pool[tpool].name, msgpool))     break;   }   /* Allocate new heap if needed */   if(tpool==cur_pool)   {    if(cur_pool>=sizeof(pool))    {     printf("Too many message groups!\n");     exit(4);    }    strcpy(pool[tpool].name, msgpool);    pool[tpool].msgs=0;    pool[tpool].crc32=CRC_MASK;    pool[tpool].safesize=POOL_R_INC;    pool[tpool].data=(char *)malloc_msg(POOL_R_INC);    pool[tpool].st_class=toupper(msgtype[0])=='N'?'N':'F';    sprintf(pool[tpool].data, "%cMSGP %s []={", pool[tpool].st_class, msgpool);    pool[tpool].columns=pool[tpool].indent=strlen(pool[tpool].data);    cur_pool++;   }   pool[tpool].msgs++;   if(strlen(pool[tpool].data)+strlen(msgname)+pool[tpool].indent+16>pool[tpool].safesize)   {    if((pool[tpool].safesize+=POOL_R_INC)>POOL_SIZE)    {     printf("Message pool for %s exceeded %u bytes, exiting\n", msgpool, POOL_SIZE);    }    if((pool[tpool].data=realloc(pool[tpool].data, pool[tpool].safesize))==NULL)    {     printf("Unexpected lack of memory!r\n");     exit(5);    }   }   if((pool[tpool].columns+=strlen(msgname))>COLUMNS)   {    strcat(pool[tpool].data, "\n");    pool[tpool].columns=pool[tpool].indent;    pool[tpool].data[strlen(pool[tpool].data)+pool[tpool].indent]='\0';    memset(pool[tpool].data+strlen(pool[tpool].data), 32, pool[tpool].indent);   }   strcat(pool[tpool].data, msgname);   strcat(pool[tpool].data, ", ");   strcpy(msg_buffer, msg_buffer+1);   buf_len=strlen(msg_buffer);   msg_buffer[--buf_len]='\0';   patch_string(msg_buffer);   crc32term=pool[tpool].crc32;   crc32_for_string(msg_buffer);   pool[tpool].crc32=crc32term;  } } fputs("\n", hfile); /* First, flush the message pools... */ for(tpool=0; tpool<cur_pool; tpool++) {  strcat(pool[tpool].data, "NULL};\n\n");  fputs(pool[tpool].data, ifile);  free(pool[tpool].data);  /* ...by the way, flushing the CRC-32 values */  fprintf(hfile, "#define %s_CRC32 0x%08lx\n", pool[tpool].name, pool[tpool].crc32);  fprintf(hfile, "extern %cMSGP %s[];\n", pool[tpool].st_class, pool[tpool].name); } /* Now, put an ending LF to all files */ fputs("\n", ifile); fputs("\n", nfile); fputs("\n", ffile); fputs("\n", hfile); fclose(ifile); fclose(nfile); fclose(ffile); fclose(hfile); free(msg_buffer); return(0);                            /* Report no error */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -