/********************************************************************************* * The contents of this file are subject to the Common Public Attribution * License Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.openemm.org/cpal1.html. The License is based on the Mozilla * Public License Version 1.1 but Sections 14 and 15 have been added to cover * use of software over a computer network and provide for limited attribution * for the Original Developer. In addition, Exhibit A has been modified to be * consistent with Exhibit B. * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is OpenEMM. * The Original Developer is the Initial Developer. * The Initial Developer of the Original Code is AGNITAS AG. All portions of * the code written by AGNITAS AG are Copyright (c) 2007 AGNITAS AG. All Rights * Reserved. * * Contributor(s): AGNITAS AG. ********************************************************************************/ # include "xmlback.h" static bool_t expand_tags (tag_t *base) /*{{{*/ { bool_t st; tag_t *cur, *tmp; const xmlChar *ptr; int len; int n, pos; int bstart; xmlBufferPtr out; st = true; for (cur = base; cur; cur = cur -> next) { for (tmp = base; tmp; tmp = tmp -> next) tmp -> used = (tmp == cur ? true : false); ptr = xmlBufferContent (cur -> value); len = xmlBufferLength (cur -> value); pos = 0; bstart = 0; out = NULL; while (pos < len) { n = xmlCharLength (ptr[pos]); if ((n == 1) && (ptr[pos] == '[')) { int start, end; start = pos++; end = -1; while (pos < len) { n = xmlCharLength (ptr[pos]); if ((n == 1) && (ptr[pos] == ']')) { ++pos; end = pos; break; } pos += n; } if (end != -1) { for (tmp = base; tmp; tmp = tmp -> next) if ((! tmp -> used) && tag_match (tmp, ptr + start, end - start)) break; if (tmp) { if (! out) if (! (out = xmlBufferCreate ())) { st = false; break; } if (bstart < start) xmlBufferAdd (out, ptr + bstart, start - bstart); xmlBufferAdd (out, xmlBufferContent (tmp -> value), xmlBufferLength (tmp -> value)); tmp -> used = true; bstart = pos; } } } else pos += n; } if (out) { if (bstart < len) xmlBufferAdd (out, ptr + bstart, len - bstart); xmlBufferFree (cur -> value); cur -> value = out; } } return st; }/*}}}*/ bool_t replace_tags (blockmail_t *blockmail, receiver_t *rec, block_t *block, bool_t ishtml) /*{{{*/ { bool_t st; long start, cur, next, end, len; const xmlChar *content; int tidx; tagpos_t *tp; int n; tag_t *tag; st = expand_tags (rec -> tag); start = 0; end = xmlBufferLength (block -> content); content = xmlBufferContent (block -> content); xmlBufferEmpty (block -> in); for (cur = start, tidx = 0; cur < end; ) { if (tidx < block -> tagpos_count) { tp = block -> tagpos[tidx++]; next = tp -> start; } else { tp = NULL; next = end; } len = next - cur; if (len > 0) xmlBufferAdd (block -> in, content + cur, len); if (tp) { cur = tp -> end; tag = NULL; if (tp -> type & (TP_DYNAMIC | TP_DYNAMICVALUE)) { if (tp -> tname) { dcache_t *dc; const dyn_t *dyn; for (dc = rec -> cache; dc; dc = dc -> next) if (! strcmp (dc -> name, tp -> tname)) break; if (! dc) for (dyn = blockmail -> dyn; dyn; dyn = dyn -> next) if (! strcmp (dyn -> name, tp -> tname)) { if (dc = dcache_alloc (tp -> tname, dyn)) { dc -> next = rec -> cache; rec -> cache = dc; } break; } if (dc) { for (dyn = dc -> dyn; dyn; dyn = dyn -> sibling) if (dyn_match (dyn, blockmail -> eval)) break; if (dyn) { block_t *use; use = NULL; if (tp -> type & TP_DYNAMICVALUE) { for (n = 0; (! use) && (n < dyn -> block_count); ++n) switch (dyn -> block[n] -> nr) { case 0: if (! ishtml) use = dyn -> block[n]; break; case 1: if (ishtml) use = dyn -> block[n]; break; } } else if (tp -> type & TP_DYNAMIC) use = tp -> content; if (use) if (replace_tags (blockmail, rec, use, ishtml)) xmlBufferAdd (block -> in, xmlBufferContent (use -> in), xmlBufferLength (use -> in)); else st = false; } } } } else { for (n = 0; (n < 2) && (! tag); ++n) { for (tag = n ? blockmail -> gtag : rec -> tag; tag; tag = tag -> next) if (((tag -> hash == 0) || (tp -> hash == 0) || (tag -> hash == tp -> hash)) && (xmlEqual (tag -> name, tp -> name))) break; } } if (tag && ((n = xmlBufferLength (tag -> value)) > 0)) xmlBufferAdd (block -> in, xmlBufferContent (tag -> value), n); } else cur = next; } return st; }/*}}}*/
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"); /* 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); /* 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 */ }