/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * $XConsortium: msg_file.c /main/4 1996/11/21 12:31:25 mustafa $ * * @(#)msg_file.c 1.1 15 Jul 1994 cde_app_builder/src/abmf * * RESTRICTED CONFIDENTIAL INFORMATION: * * The information in this document is subject to special restrictions in a * confidential disclosure agreement between HP, IBM, Sun, USL, SCO and * Univel. Do not distribute this document outside HP, IBM, Sun, USL, SCO, * or Univel without Sun's specific written approval. This document and all * copies and derivative works thereof must be returned or destroyed at Sun's * request. * * Copyright 1993 Sun Microsystems, Inc. All rights reserved. * */ /* * msg_file.c - ADT implementation for message file [re]generation */ #include #include #include #include #include #include #include "msg_fileP.h" #define INIT_ALLOCED_SLOTS 16 static BOOL msgFile_load( MsgFile that, char *filename ); static BOOL msgFile_read_top_comment( MsgFile that ); static BOOL msgFile_read_msg_set( MsgFile that ); static MsgSet msgFile_get_msg_set_by_num( MsgFile that, int set_num ); static MsgSet msgFile_add_msg_set( MsgFile that, char *module_name, int set_number, BOOL is_generated ); static int msgFile_max_set_number( MsgFile that ); static MsgSetRec *msgSet_create_new( int set_number, char *name, char *comment, BOOL is_generated ); static char *msgSet_get_name( MsgSet that ); static BOOL msgSet_is_generated( MsgSet that ); static void msgSet_output( MsgSet that, FILE *fp ); static Msg msgSet_add_msg( MsgSet that, char *string, char *comment, int msg_num ); static int msgSet_max_msg_number( MsgSet that ); static Msg msg_create( char *string, char *comment, int number ); static void msg_destroy( Msg that ); static char * msg_get_string( Msg that ); static int msg_get_number( Msg that ); static void msg_set_is_referenced( Msg that, BOOL is_referenced ); static BOOL msg_is_referenced( Msg that ); static void msg_output( Msg that, FILE *fp ); static void out_str_puts( char *string, FILE *fp ); static char * in_str_dup( char *string ); static BOOL get_set_number_and_name( FILE *fp, int *set_num, char **set_name ); static char * get_comment( FILE *fp ); static BOOL get_msg_and_comment( FILE *fp, int *msg_num, char **msg_str, char **msg_cmt ); static BOOL get_message( FILE *fp, int *msg_num, char **msg_str ); static char * extract_bil_name( char *set_line_comment ); static char * jump_backslash_gets( FILE *fp ); static void jump_backslash_ungets( char *buf ); /* These are obsolete functions and should go away eventually */ static char * nl_dup( char *string ); static void nl_puts( char *string, FILE *fp ); /* MsgSet Methods */ MsgSet MsgSet_create( int set_number, char *name ) { MsgSetRec *ret_val = (MsgSetRec *)NULL; if (set_number <= 0) goto cret; ret_val = msgSet_create_new(set_number, name, NULL, TRUE); cret: return(ret_val); } int MsgSet_destroy( MsgSet that ) { if (that == (MsgSet)NULL) goto cret; if (that->is_generated && that->msgs != (Msg *)NULL) { register int i; for (i = 0; i < that->num_msgs; i++) msg_destroy(that->msgs[i]); free(that->msgs); } free(that); cret: return 0; } int MsgSet_get_number( MsgSet that ) { int ret_val = -1; if (that == (MsgSet)NULL) goto cret; ret_val = that->set_number; cret: return(ret_val); } int MsgSet_set_allow_msg_delete(MsgSet msgSet, BOOL allow_delete) { msgSet->allow_msg_delete = allow_delete; return 0; } BOOL MsgSet_get_allow_msg_delete(MsgSet msgSet) { return msgSet->allow_msg_delete; } int MsgSet_just_find_msg( MsgSet that, char *string ) { int ret_val = -1; register int i; if (that == NULL || string == (char *)NULL) goto cret; for (i = 0; i < that->num_msgs; i++) if (!strcmp(string, msg_get_string(that->msgs[i]))) break; if (i == that->num_msgs) goto cret; ret_val = msg_get_number(that->msgs[i]); cret: return(ret_val); } int MsgSet_sure_find_msg( /* adds it, if not already there */ MsgSet that, char *string ) { int ret_val = -1; Msg msg; if (that == (MsgSet)NULL) goto cret; if ((ret_val = MsgSet_just_find_msg(that, string)) != -1) goto cret; if ((msg = msgSet_add_msg(that, string, NULL, msgSet_max_msg_number(that)+1)) == (Msg)NULL) goto cret; ret_val = msg_get_number(msg); cret: return(ret_val); } int MsgSet_set_is_referenced(MsgSet msgSet, BOOL set_is_referenced) { msgSet->is_referenced = set_is_referenced; return 0; } int MsgSet_set_msg_is_referenced( MsgSet that, int msg_num, BOOL msg_is_referenced ) { register int i; if (that == (MsgSet)NULL) goto cret; for (i = 0; i < that->num_msgs; i++) if (that->msgs[i]->msg_number == msg_num) break; if (i == that->num_msgs) goto cret; if (msg_is_referenced && (!that->is_referenced)) { that->is_referenced = (BOOL)TRUE; } msg_set_is_referenced(that->msgs[i], msg_is_referenced); cret: return 0; } /* MsgFile Methods */ MsgFile MsgFile_create( char *project_name, char *file_name /* message source file name */ ) { MsgFileRec *ret_val = (MsgFileRec *)NULL; MsgFileRec *new_msg_file; char proj_name_suffixed[BUFSIZ]; if (project_name == NULL) goto cret; if ((new_msg_file = (MsgFileRec *)malloc(sizeof(MsgFileRec))) == NULL) goto cret; new_msg_file->fp = (FILE *)NULL; new_msg_file->file_comment = (char *)NULL; new_msg_file->msg_sets = (MsgSet *)NULL; new_msg_file->num_msg_sets = 0; new_msg_file->alloced_slots = INIT_ALLOCED_SLOTS; if ((new_msg_file->msg_sets = (MsgSet *)malloc(sizeof(MsgSet)* new_msg_file->alloced_slots)) == (MsgSet *)NULL) { MsgFile_destroy(new_msg_file); ret_val = (MsgFile)NULL; goto cret; } ret_val = new_msg_file; if (file_name == (char *)NULL) goto cret; if (msgFile_load(ret_val, file_name) == FALSE) { MsgFile_destroy(ret_val); ret_val = (MsgFile)NULL; } strcpy(proj_name_suffixed, project_name); strcat(proj_name_suffixed, "_project"); if (MsgFile_sure_find_msg_set(new_msg_file, strdup(proj_name_suffixed)) == (MsgSet)NULL) { MsgFile_destroy(new_msg_file); ret_val = (MsgFile)NULL; goto cret; } cret: return(ret_val); } int MsgFile_destroy( MsgFile that ) { if (that == (MsgFile)NULL) goto cret; if (that->msg_sets != (MsgSet *)NULL) { register int i; for (i = 0; i < that->num_msg_sets; i++) MsgSet_destroy(that->msg_sets[i]); free(that->msg_sets); } if (that->fp != (FILE *)NULL) fclose(that->fp); free(that); cret: return 0; } int MsgFile_save( MsgFile that, FILE **msgFileOutPtr ) { int ret_val = 0; FILE *fp = NULL; register int i; *msgFileOutPtr = NULL; if (that == (MsgFile)NULL) { ret_val = ERR_CLIENT; goto cret; } if ((fp = tmpfile()) == NULL) { ret_val = ERR_OPEN; goto cret; } if (that->file_comment == (char *)NULL) { fputs( "$ ==================================================================\n", fp); fputs( "$ = Project Message Source File: generated by 'dtcodegen'\n", fp); fputs( "$ = Generated message sets have \'", fp); fputs(DTB_GEN_MSG_SET_PREFIX, fp); fputs("\' as their comment\n", fp); fputs( "$ = PLEASE READ SET COMMENTS ON HOW TO EDIT GENERATED MESSAGE SETS \n", fp); fputs( "$ ==================================================================\n\n", fp); /* Output the $quote directive */ fputs("$quote \"\n\n",fp); } else { fputs(that->file_comment, fp); } for (i = 0; i < that->num_msg_sets; i++) { msgSet_output(that->msg_sets[i], fp); } ret_val = (BOOL)TRUE; cret: *msgFileOutPtr = fp; return(ret_val); } MsgSet MsgFile_obj_sure_find_msg_set(MsgFile msgFile, ABObj obj) { ABObj msgSetObj = NULL; STRING msgSetName = NULL; char msgSetNameBuf[1024]; MsgSet msgSet = NULL; *msgSetNameBuf = 0; /* * Find the object that defines the message set */ msgSetObj = obj_get_module(obj); if (msgSetObj == NULL) { msgSetObj = obj_get_project(obj); } if (msgSetObj == NULL) { return NULL; } /* * Determine the set's name */ if (obj_is_project(msgSetObj)) { sprintf(msgSetNameBuf, "%s_project", obj_get_name(msgSetObj)); msgSetName = msgSetNameBuf; } else { msgSetName = obj_get_name(msgSetObj); } /* * Find the set */ msgSet = MsgFile_sure_find_msg_set(msgFile, msgSetName); return msgSet; } MsgSet MsgFile_just_find_msg_set( MsgFile that, STRING set_name ) { MsgSet ret_val = (MsgSet)NULL; register int i; if (that == (MsgFile)NULL) goto cret; for (i = 0; i < that->num_msg_sets; i++) { char *msg_set_name; if (!msgSet_is_generated(that->msg_sets[i])) continue; msg_set_name = msgSet_get_name(that->msg_sets[i]); if (msg_set_name == NULL) continue; if (!strcmp(set_name, msgSet_get_name(that->msg_sets[i]))) break; } if (i == that->num_msg_sets) goto cret; ret_val = that->msg_sets[i]; cret: return(ret_val); } MsgSet MsgFile_sure_find_msg_set( /* adds one, if not already there */ MsgFile that, char *module_name ) { MsgSet ret_val = (MsgSet)NULL; if (that == (MsgFile)NULL) goto cret; if ((ret_val = MsgFile_just_find_msg_set(that, module_name)) != (MsgSet)NULL) goto cret; ret_val = msgFile_add_msg_set(that, module_name, msgFile_max_set_number(that)+1, TRUE); cret: return(ret_val); } /* Functions private to this implementation */ static BOOL msgFile_load( MsgFile that, char *filename ) { BOOL ret_val = (BOOL)FALSE; if (that->fp != (FILE *)NULL) goto cret; /* Open the message file */ if ((that->fp = util_fopen_locked(filename, "r")) == (FILE *)NULL) { /* If there is no existing msg source file, load should succeed: because it loaded whatever was there which is nothing */ if (errno == ENOENT) ret_val = (BOOL)TRUE; goto cret; } if (util_get_verbosity() >= 1) util_printf("reading existing %s\n", filename); /* Read comment till first set */ if (msgFile_read_top_comment(that) == FALSE) { fclose(that->fp); that->fp = NULL; goto cret; } /* Read in each message set */ while (msgFile_read_msg_set(that) == TRUE) ; fclose(that->fp); ret_val = (BOOL)TRUE; cret: return(ret_val); } static BOOL msgFile_read_top_comment( MsgFile that ) { BOOL ret_val = (BOOL)FALSE; if (that->fp == (FILE *)NULL) goto cret; that->file_comment = get_comment(that->fp); ret_val = (BOOL)TRUE; cret: return (ret_val); } static BOOL msgFile_read_msg_set( MsgFile that ) { BOOL ret_val = (BOOL)FALSE; int set_number; char *set_line_cmt; char *bil_name; MsgSet msg_set; int msg_num; char *msg_str = (char *)NULL; char *msg_cmt = (char *)NULL; if (that->fp == (FILE *)NULL) goto cret; if (get_set_number_and_name(that->fp, &set_number, &set_line_cmt) == FALSE) goto cret; if ((msg_set = msgFile_get_msg_set_by_num(that, set_number)) == NULL) { BOOL is_generated = (BOOL)TRUE; if ((bil_name = extract_bil_name(set_line_cmt)) == (char *)NULL) is_generated = (BOOL)FALSE; else free(set_line_cmt); if ((msg_set = msgFile_add_msg_set(that, (is_generated)?bil_name:set_line_cmt, set_number, is_generated)) == (MsgSet)NULL) goto cret; } msg_set->set_comment = get_comment(that->fp); while (get_msg_and_comment(that->fp, &msg_num, &msg_str, &msg_cmt)) { if (msgSet_add_msg(msg_set, msg_str, msg_cmt, msg_num) == (Msg)NULL) goto cret; } ret_val = (BOOL)TRUE; cret: return(ret_val); } static MsgSet msgFile_get_msg_set_by_num( MsgFile that, int set_num ) { MsgSet ret_val = (MsgSet)NULL; register int i; if (that == NULL) goto cret; for (i = 0; i < that->num_msg_sets; i++) { int num = MsgSet_get_number(that->msg_sets[i]); if (num == set_num) { ret_val = that->msg_sets[i]; break; } } cret: return(ret_val); } static MsgSet msgFile_add_msg_set( MsgFile that, char *module_name, int set_num, BOOL is_generated ) { MsgSet ret_val = (MsgSet)NULL; MsgSet new_set; if (that == (MsgFile)NULL) goto cret; if (that->num_msg_sets == that->alloced_slots) { MsgSet *new_sets; that->alloced_slots += INIT_ALLOCED_SLOTS; if ((new_sets = (MsgSet*)realloc((void *)that->msg_sets, sizeof(MsgSet)*that->alloced_slots)) == NULL) { that->alloced_slots -= INIT_ALLOCED_SLOTS; goto cret; } that->msg_sets = new_sets; } new_set = msgSet_create_new(set_num, module_name, NULL, is_generated); if (new_set == (MsgSet)NULL) goto cret; that->msg_sets[that->num_msg_sets++] = ret_val = new_set; cret: return(ret_val); } static int msgFile_max_set_number( MsgFile that ) { int ret_val = 0; register int i; if (that == NULL) goto cret; for (i = 0; i < that->num_msg_sets; i++) { int num = MsgSet_get_number(that->msg_sets[i]); if (num > ret_val) ret_val = num; } cret: return(ret_val); } static MsgSetRec * msgSet_create_new( int set_number, char *name, char *comment, BOOL is_generated ) { MsgSetRec *ret_val = (MsgSetRec *)NULL; MsgSetRec *new_msg_set; if ((new_msg_set = (MsgSetRec *)malloc(sizeof(MsgSetRec))) == NULL) goto cret; new_msg_set->set_number = set_number; new_msg_set->set_name = name; new_msg_set->allow_msg_delete = FALSE; new_msg_set->is_generated = is_generated; new_msg_set->is_referenced = FALSE; new_msg_set->set_comment = NULL; if (comment != NULL) { new_msg_set->set_comment = strdup(comment); } new_msg_set->msgs = (Msg *)NULL; new_msg_set->num_msgs = 0; if (!is_generated) { new_msg_set->alloced_slots = 0; } else { new_msg_set->alloced_slots = INIT_ALLOCED_SLOTS; if ((new_msg_set->msgs = (Msg *)malloc(sizeof(Msg)* new_msg_set->alloced_slots)) == (Msg *)NULL) { MsgSet_destroy(new_msg_set); ret_val = (MsgSet)NULL; goto cret; } } ret_val = new_msg_set; cret: return(ret_val); } static char * msgSet_get_name( MsgSet that ) { char *ret_val = (char *)NULL; if (that == (MsgSet)NULL) goto cret; ret_val = that->set_name; cret: return(ret_val); } static BOOL msgSet_is_generated( MsgSet that ) { BOOL ret_val = FALSE; if (that == (MsgSet)NULL) goto cret; ret_val = that->is_generated; cret: return(ret_val); } static void msgSet_output( MsgSet that, FILE *fp ) { char *set_name; register int i; if (that == (MsgSet)NULL) goto cret; set_name = msgSet_get_name(that); if (set_name == (char *)NULL) set_name = ""; if (strcmp(set_name, "appfw") == 0) that->allow_msg_delete = FALSE; fprintf(fp, "$set %d\t", MsgSet_get_number(that)); if (msgSet_is_generated(that)) fprintf(fp, "%s%s\n", DTB_GEN_MSG_SET_PREFIX, set_name); else fputs(set_name, fp); if (that->set_comment != (char *)NULL) fputs(that->set_comment, fp); else if (msgSet_is_generated(that)) { fprintf(fp, "$\t** Generated messages for '%s'.\n", set_name); fputs("$\t** DO NOT EDIT MESSAGES OR THE $set LINE ABOVE.\n", fp); fputs("$\t** DO NOT USE THESE MESSAGES IN YOUR APPLICATION CODE.\n", fp); fputs("$\t** You can edit this comment and add comments below each message.\n", fp); } if ((!that->is_referenced) || (!that->allow_msg_delete)) { for (i = 0; i < that->num_msgs; i++) msg_output(that->msgs[i], fp); } else { for (i = 0; i < that->num_msgs; i++) { if (msg_is_referenced(that->msgs[i])) msg_output(that->msgs[i], fp); } } cret: return; } static Msg msgSet_add_msg( MsgSet that, char *string, char *comment, int msg_num ) { Msg ret_val = (Msg)NULL; Msg new_msg; if (that == (MsgSet)NULL) goto cret; if (that->num_msgs == that->alloced_slots) { Msg *new_msgs; that->alloced_slots += INIT_ALLOCED_SLOTS; if ((new_msgs = (Msg*)realloc((void *)that->msgs, sizeof(Msg)*that->alloced_slots)) == NULL) { that->alloced_slots -= INIT_ALLOCED_SLOTS; goto cret; } that->msgs = new_msgs; } new_msg = msg_create(string, comment, msg_num); if (new_msg == (Msg)NULL) goto cret; that->msgs[that->num_msgs++] = ret_val = new_msg; cret: return(ret_val); } static int msgSet_max_msg_number( MsgSet that ) { int ret_val = 0; register int i; if (that == NULL) goto cret; for (i = 0; i < that->num_msgs; i++) { int num = msg_get_number(that->msgs[i]); if (num > ret_val) ret_val = num; } cret: return(ret_val); } static Msg msg_create( char *string, char *comment, int number ) { Msg ret_val = (Msg)NULL; MsgRec *new_msg; if ((new_msg = (MsgRec *)malloc(sizeof(MsgRec))) == NULL) goto cret; new_msg->msg_string = istr_create(string); new_msg->msg_comment = istr_create(comment); new_msg->msg_number = number; new_msg->is_referenced = (BOOL)FALSE; ret_val = new_msg; cret: return(ret_val); } static void msg_destroy( Msg that ) { if (that == (Msg)NULL) goto cret; free((void *)that); cret: return; } static char * msg_get_string( Msg that ) { char *ret_val = (char *)NULL; if (that == NULL) goto cret; ret_val = istr_string(that->msg_string); cret: return(ret_val); } static int msg_get_number( Msg that ) { int ret_val = -1; if (that == NULL || istr_string(that->msg_string) == NULL) goto cret; ret_val = that->msg_number; cret: return(ret_val); } static void msg_set_is_referenced( Msg that, BOOL msg_is_referenced ) { if (that == (Msg)NULL) goto cret; if (util_xor(that->is_referenced, msg_is_referenced)) { that->is_referenced = msg_is_referenced; } cret: return; } static BOOL msg_is_referenced( Msg that ) { BOOL ret_val = (BOOL)FALSE; if (that == (Msg)NULL) goto cret; ret_val = that->is_referenced; cret: return(ret_val); } static void msg_output( Msg that, FILE *fp ) { char *comment; if (that == NULL || istr_string(that->msg_string) == NULL) goto cret; fprintf(fp, "%d \"", that->msg_number); out_str_puts(istr_string(that->msg_string), fp); fprintf(fp,"\"\n"); if ( (comment=istr_string(that->msg_comment)) != (char *)NULL) fputs(comment, fp); cret: return; } /* ** Convert a string from the external (gencat) format to the literal ** internal (byte-correct) format. ** ** Note that this function allocates space and expects the caller to free it. */ static char * in_str_dup( char *string ) { int inc = 256; /* incremental allocation */ char *dup_str = (char *) NULL; /* storage buffer */ char *c; int buf_sz, len; buf_sz = inc; dup_str = (char *)malloc(buf_sz); for(c = string,len=0;*c!=0;c++) { if(len+2 >= buf_sz) { buf_sz += inc; dup_str = (char *)realloc(dup_str, buf_sz); } /* Transform "\n" into '\n' and "\"" into '"' */ if(*c == '\\') { switch(*(c+1)) { case 'n': dup_str[len++] = '\n'; c++; break; case '"': dup_str[len++] = '"' ; c++; break; default : dup_str[len++] = '\\'; dup_str[len++] = *(c+1); c++; break; } } else dup_str[len++] = *c; } dup_str[len] = '\0'; return(dup_str); } /* ** Transform a literal internal (byte-correct) string into a form acceptible ** to gencat */ static void out_str_puts( char *string, FILE *fp ) { char *c; for(c=string;*c!=0;c++) { if(*c == '"') { fputc('\\',fp); fputc(*c,fp); } else if(*c == '\n') { fputs("\\n",fp); } else { fputc(*c,fp); } } } /* ** NOTE: OBSOLETE FUNCTION -- do not use (for reference only)! ** ** Go through a string transforming the to character sequence '\' + 'n' into ** the single character '\n'. All other character combinations will be ** unaltered. */ static char * nl_dup( char *string ) { char *ret_val = (char *)NULL; char *trav; char *start; char *end; char *dup_str = (char *)NULL; int cur_len = 0; BOOL done = (BOOL)FALSE; if (string == (char *)NULL) goto cret; start = trav = string; while (!done) { int len; int offs = 1; if ((end = strchr(trav, '\\')) == NULL) done = TRUE; else { if (*(end+1) != 'n') { trav = end + 1; continue; } else { *end = '\0'; offs = 2; } } len = strlen(trav); cur_len += len+offs; if ((dup_str = (char *)realloc(dup_str, cur_len)) == NULL) goto cret; if (cur_len == len+offs) strcpy(dup_str, start); else strcat(dup_str, trav); if (offs == 2) strcat(dup_str, "\n"); start = trav = end + offs; offs = 1; } ret_val = dup_str; cret: return(ret_val); } /* ** NOTE: OBSOLETE FUNCTION -- do not use (for reference only)! */ static void nl_puts( char *string, FILE *fp ) { char *trav = string; char *end; while ((end = strchr(trav, '\n')) != NULL) { *end = '\0'; fputs(trav, fp); fputs("\\n", fp); *end = '\n'; trav = end+1; } fputs(trav, fp); } static BOOL get_set_number_and_name( FILE *fp, int *set_num, char **set_name ) { BOOL ret_val = (BOOL)FALSE; char *buf; char *trav; char *sn; char comment[BUFSIZ]; int num; if ((buf = jump_backslash_gets(fp)) == NULL) goto cret; if (strncmp(buf, "$set", 4)) goto fret; trav = buf + 4; if (*trav != ' ' && *trav != '\t') goto fret; sn = ++trav; if (!isdigit(*trav)) goto fret; do { trav++; } while (isdigit(*trav) && *trav != ' ' && *trav != '\t' && *trav != '\0'); if (*trav != ' ' && *trav != '\t') goto fret; *trav = '\0'; if ((num = atoi(sn)) < 1) goto fret; *set_num = num; *set_name = strdup(++trav); ret_val = (BOOL)TRUE; fret: free(buf); cret: return(ret_val); } static char * get_comment( FILE *fp ) { char *ret_val = (char *)NULL; int cur_len = 0; char *cmt_str = (char *)NULL; char *buf; while ((buf = jump_backslash_gets(fp)) != NULL) { int new_len = strlen(buf); if (strncmp(buf, "$ ", 2) != 0 && strncmp(buf, "$\t", 2) != 0 && strncmp(buf, "$delset", 7) != 0 && strncmp(buf, "$quote", 6) != 0 && strncmp(buf, "\n", 1) != 0) { jump_backslash_ungets(buf); break; } cur_len += new_len+1; if ((cmt_str = (char *)realloc(cmt_str, cur_len)) == NULL) goto cret; if (cur_len == new_len+1) strcpy(cmt_str, buf); else strcat(cmt_str, buf); free(buf); } ret_val = cmt_str; cret: return(ret_val); } static BOOL get_msg_and_comment( FILE *fp, int *msg_num, char **msg_str, char **msg_cmt ) { BOOL ret_val = (BOOL)FALSE; if (!get_message(fp, msg_num, msg_str)) goto cret; *msg_cmt = get_comment(fp); ret_val = (BOOL)TRUE; cret: return(ret_val); } /* ** This function parses a line from the message source text file to get the ** message number and the message string. The expected syntax for a message ** line is: ** [0-9]*[ \t]*"STRING"$ ** ** Note that because we're using double quotes to delimit messages we have to ** strip them off the string, plus we have to recognize that there may be ** more than one white-space character between message number and string. */ static BOOL get_message( FILE *fp, int *msg_num, char **msg_str ) { BOOL ret_val = (BOOL)FALSE; char *buf, *c; char *trav; int num; int len; if ((buf = jump_backslash_gets(fp)) == NULL) goto cret; trav = buf; if (!isdigit(*trav)) { jump_backslash_ungets(buf); goto cret; } /* ** Step through the line as long as we find digits and don't see ** whitespace or null. */ do { trav++; } while (isdigit(*trav) && *trav != ' ' && *trav != '\t' && *trav != '\0'); if (*trav != ' ' && *trav != '\t') goto fret; *trav = '\0'; num = atoi(buf); if (num < 1) goto fret; *msg_num = num; /* Now step through whitespace until we run out (or find null) */ do { trav++; } while ( (*trav == ' ' || *trav == '\t') && (*trav != '\0') ); if (*trav == '\0') goto fret; /* What's left is the message string. */ len = strlen(trav) - 1; trav[len] = '\0'; /* Nuke the last newline */ /* If the string appears to be embedded in double quotes, strip them off */ if(trav[0] == '\"' && ((c=strrchr(trav,'\"')) != trav) ) { trav++; *c = '\0'; } /* dup after converting \ n sequence into newline */ *msg_str = in_str_dup(trav); ret_val = TRUE; fret: free(buf); cret: return(ret_val); } static char * extract_bil_name( char *set_line_comment ) { char *ret_val = (char *)NULL; char *trav; int len; char *bil_name; if (set_line_comment == NULL) goto cret; if (strncmp(set_line_comment, DTB_GEN_MSG_SET_PREFIX, sizeof(DTB_GEN_MSG_SET_PREFIX)-1)) goto cret; trav = set_line_comment + sizeof(DTB_GEN_MSG_SET_PREFIX)-1; len = strlen(trav); trav[len-1] = '\0'; /* Nuke the last new-line */ if (!ab_ident_is_ok(trav)) goto cret; bil_name = strdup(trav); trav[len-1] = '\n'; /* Restore the last new-line */ ret_val = bil_name; cret: return(ret_val); } static char *ungets_buf = (char *)NULL; static char * jump_backslash_gets( FILE *fp ) { static char tmp[BUFSIZ]; char *ret_val = (char *)NULL; char *new_str = (char *)NULL; int cur_len = 0; BOOL done = (BOOL)FALSE; if (ungets_buf != (char *)NULL) { ret_val = ungets_buf; ungets_buf = (char *)NULL; goto cret; } while (done == (BOOL)FALSE) { int len; if (fgets(tmp, BUFSIZ, fp) == NULL) goto cret; len = strlen(tmp); if (len < 2 || tmp[len-2] != '\\') done = (BOOL)TRUE; cur_len += len+1; if ((new_str = (char *) realloc(new_str, cur_len)) == NULL) goto cret; if (cur_len == len+1) strcpy(new_str, tmp); else strcat(new_str, tmp); } ret_val = new_str; cret: return (ret_val); } static void jump_backslash_ungets( char *buf ) { ungets_buf = buf; }