/* $Id$ * * To populate the registry_db, construct a codeset registry text file based * on the OSF's Character and Code Set Registry. See DCE RFC 40.1 for details * on obtaining the full text for the current registry. Once you have composed * a text file containing all the desired codeset information, build and run * mkcsregdb. The source is in $ACE_ROOT/apps/mkcsregdb. It will generate a new * copy of this file, with the registry_db_ array properly initialized. */ // FUZZ: disable check_for_streams_include #include "ace/streams.h" #include "ace/Codeset_Registry.h" #include "ace/Log_Msg.h" #include "ace/OS_NS_sys_stat.h" #include "ace/OS_NS_time.h" #include "ace/OS_NS_stdio.h" #include "ace/OS_NS_stdlib.h" #include "ace/OS_NS_string.h" #include "ace/OS_NS_unistd.h" class csdb_generator : public ACE_Codeset_Registry { public: csdb_generator (); int read_from (const char *source); int init_output (const char *srcfile); int write_entry (); int fini_output (const char *target); int read_line (); void write_dummy_entry(); void fail(const char *msg); private: static const char * tags_[]; static int max_line_; int count_; int in_entry_; registry_entry entry_; int linecounter_; char *source_line_; char *line_data_; ifstream *inf_; FILE *outf_; char tempfilename_[MAXPATHLEN]; char *ace_src_; }; int csdb_generator::max_line_ = 1024; const char * csdb_generator::tags_[] = { "start", "end", "description ", "loc_name ", "rgy_value ", "char_values ", "max_bytes ", 0 }; csdb_generator::csdb_generator () :count_(0), in_entry_(0), linecounter_(0), source_line_ (new char[max_line_]), line_data_ (0), inf_ (0), outf_ (0) { ace_src_ = ACE_OS::getenv("ACE_ROOT"); tempfilename_[0] = '\0'; } void csdb_generator::fail (const char *msg) { ACE_ERROR ((LM_ERROR,"Error, line %d: %s\n",linecounter_,msg)); ACE_OS::fclose (outf_); ACE_OS::unlink (tempfilename_); ACE_OS::exit (-1); } int csdb_generator::read_line() { inf_->getline (source_line_,max_line_); line_data_ = 0; char *cpos = ACE_OS::strchr (source_line_,'#'); if (cpos == 0) cpos = source_line_ + ACE_OS::strlen(source_line_); while (cpos > source_line_ && ACE_OS::strchr(" \t",*(cpos - 1))) cpos--; *cpos = 0; if (cpos == source_line_) return 0; for (int i = 0; tags_[i]; i++) { cpos = ACE_OS::strstr (source_line_,tags_[i]); if (cpos == 0) // not found continue; if (cpos > source_line_) // make sure it's first token { char *tpos = cpos-1; while (tpos > source_line_ && ACE_OS::strchr(" \t",*tpos)) tpos--; if (tpos > source_line_) continue; } if (i == 0 && in_entry_) fail ("\"start\" encountered twice before \"end\""); if (i > 0 && !in_entry_) { char *emsg = new char[100]; ACE_OS::sprintf (emsg,"\"%s\" encountered before \"start\"",tags_[i]); fail (emsg); } if (i > 1) { line_data_ = cpos + ACE_OS::strlen(tags_[i]); while (*line_data_ && ACE_OS::strchr(" \t",(*line_data_))) line_data_++; } return i+1; } return -1; } int csdb_generator::read_from (const char *srcfile) { inf_ = new ifstream(srcfile); char *ptr; while (inf_->good() && !inf_->eof()) { linecounter_++; switch (read_line ()) { case -1: // bogus line fail ("unknown field tag"); break; case 0: // comment or blank line break; case 1: // start entry_.desc_ = 0; entry_.loc_name_ = 0; entry_.codeset_id_ = 0; entry_.num_sets_ = 0; entry_.max_bytes_ = 0; in_entry_ = 1; break; case 2: // end if (entry_.codeset_id_ == 0) fail ("entry missing rgy_value"); if (entry_.num_sets_ == 0) fail ("entry does not include at least one char_value"); if (entry_.max_bytes_ == 0) fail ("entry does not define max_bytes"); write_entry (); delete [] const_cast (entry_.desc_); delete [] const_cast (entry_.loc_name_); count_++; in_entry_ = 0; break; case 3: // description if (entry_.desc_ != 0) fail ("duplicate description"); entry_.desc_ = ACE_OS::strdup(line_data_); break; case 4: // loc_name if (entry_.loc_name_ != 0) fail ("duplicate loc_name"); entry_.loc_name_ = ACE_OS::strdup(line_data_); break; case 5: // rgy_value if (entry_.codeset_id_ != 0) fail ("duplicate rgy_value"); entry_.codeset_id_ = ACE_OS::strtoul(line_data_,&ptr,16); if (*ptr != 0 || entry_.codeset_id_ == 0) { char emsg [100]; ACE_OS::sprintf (emsg,"invalid rgy_value, '%s'",line_data_); fail (emsg); } break; case 6: // char_values if (entry_.num_sets_ != 0) fail ("duplicate char_values"); ptr = line_data_; do { if (*ptr == ':') ptr++; ACE_CDR::UShort tmp = static_cast (ACE_OS::strtoul(ptr,&ptr,16)); if (*ptr != 0 && *ptr != ':') { char *emsg = new char [100]; ACE_OS::sprintf (emsg,"invalid symbol \'%c\' in char_values",*ptr); fail (emsg); } if (entry_.num_sets_ < max_charsets_) entry_.char_sets_[entry_.num_sets_++] = tmp; else entry_.num_sets_++; } while (*ptr == ':'); if (entry_.num_sets_ > max_charsets_) { char *emsg = new char [200]; ACE_OS::sprintf (emsg,"max of %d char_values exceeded.\nIncrease ACE_Codeset_Registry::max_charsets_ to at least %d and rebuild mkcsregdb",max_charsets_,entry_.num_sets_); fail (emsg); } break; case 7: // max_bytes if (entry_.max_bytes_ != 0) fail ("duplicate max_bytes"); entry_.max_bytes_ = static_cast (ACE_OS::strtol(line_data_,&ptr,10)); if (*ptr != 0) fail ("invalid max_bytes"); break; } } return 0; } int csdb_generator::init_output (const char *srcfile) { ACE_stat buf; if (ACE_OS::stat (srcfile,&buf) != 0) ACE_ERROR_RETURN ((LM_ERROR,"Unable to open %s\n",srcfile),-1); if (ace_src_ == 0) ACE_ERROR_RETURN ((LM_ERROR,"You must first set $ACE_ROOT\n"),-1); time_t now = ACE_OS::time(); if (ACE_OS::strlen(ace_src_) > 0) { ACE_OS::sprintf (tempfilename_, "%s%s%s", ace_src_, ACE_DIRECTORY_SEPARATOR_STR, "csdbXXXXXX"); } else { ACE_OS::strcpy (tempfilename_, "csdbXXXXXX"); } ACE_HANDLE fd = ACE_OS::mkstemp (tempfilename_); if (fd == ACE_INVALID_HANDLE) ACE_ERROR_RETURN ((LM_ERROR, "Unable to open output file, %p\n", tempfilename_), -1); outf_ = ACE_OS::fdopen (fd, "w"); ACE_OS::fprintf (outf_,"// $ID: $\n"); ACE_OS::fprintf (outf_,"/*\n * Codeset registry DB, generated %s * source: %s\n", ACE_OS::asctime (ACE_OS::localtime(&now)), srcfile); ACE_OS::fprintf (outf_," *\n * To populate the registry_db, construct a codeset registry text file based\n"); ACE_OS::fprintf (outf_," * on the OSF's Character and Code Set Registry. See DCE RFC 40.1 for details\n"); ACE_OS::fprintf (outf_," * on obtaining the full text for the current registry. Once you have composed\n"); ACE_OS::fprintf (outf_," * a text file containing all the desired codeset information, build and run\n"); ACE_OS::fprintf (outf_," * mkcsregdb. The source is in $ACE_ROOT/apps/mkcsregdb. It will generate a new\n"); ACE_OS::fprintf (outf_," * copy of this file, with the registry_db_ array properly initialized.\n */\n"); ACE_OS::fprintf (outf_,"\n#include \"ace/Codeset_Registry.h\"\n\n%s\n%s\n{\n", "ACE_Codeset_Registry::registry_entry const", "ACE_Codeset_Registry::registry_db_[] ="); return 0; } int csdb_generator::write_entry () { if (count_) ACE_OS::fprintf (outf_,",\n"); ACE_OS::fprintf (outf_," {\"%s\",\"%s\",0x%08x,%d,{", entry_.desc_, entry_.loc_name_, entry_.codeset_id_, entry_.num_sets_); for (ACE_CDR::UShort j = 0; j < entry_.num_sets_; j++) if (j+1 < entry_.num_sets_) ACE_OS::fprintf (outf_,"0x%04x,",entry_.char_sets_[j]); else ACE_OS::fprintf (outf_,"0x%04x",entry_.char_sets_[j]); ACE_OS::fprintf (outf_,"},%d}",entry_.max_bytes_); return 0; } void csdb_generator::write_dummy_entry() { entry_.desc_ = "No codesets defined"; entry_.loc_name_ = "NONE"; entry_.codeset_id_ = 0; entry_.num_sets_ = 1; entry_.char_sets_[0] = 0; entry_.max_bytes_ = 0; write_entry(); } int csdb_generator::fini_output (const char *tgt) { char *target = new char [ACE_OS::strlen(ace_src_) + ACE_OS::strlen(tgt) + 6]; ACE_OS::sprintf (target,"%s/ace/%s",ace_src_,tgt); if (count_ == 0) write_dummy_entry(); ACE_OS::fprintf (outf_,"\n};\n\nsize_t const ACE_Codeset_Registry::num_registry_entries_ = %d;\n\n",count_); ACE_OS::fclose (outf_); ACE_stat buf; if (ACE_OS::stat (target,&buf) == 0) { char fname[200]; int result = 0; for (int i = 0; result == 0; i++) { ACE_OS::sprintf (fname,"%s.%03d",target,i); result = ACE_OS::stat(fname,&buf); } ACE_DEBUG ((LM_DEBUG,"Moving $ACE_ROOT/ace/%s to $ACE_ROOT/ace%s\n", tgt,ACE_OS::strrchr(fname,'/'))); if (ACE_OS::rename (target,fname) == -1) ACE_ERROR_RETURN ((LM_ERROR,"Could not create %s\n, output stored in %s", fname,tempfilename_),-1); } ACE_DEBUG ((LM_DEBUG,"writing $ACE_ROOT/ace/%s\n",tgt)); if (ACE_OS::rename (tempfilename_,target) == -1) ACE_ERROR_RETURN ((LM_ERROR,"Could not create %s\n, output stored in %s", target,tempfilename_),-1); return 0; } int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) { ACE_CString srcname; if (argc > 1) srcname.set(argv[1]); else ACE_ERROR_RETURN ((LM_ERROR,"Usage: %s \nwhere source file is the full path to a code set registry text file.\n",argv[0]),-1); csdb_generator csdb; if (csdb.init_output(srcname.c_str()) == -1) return 0; if (csdb.read_from (srcname.c_str()) == 0) csdb.fini_output ("Codeset_Registry_db.cpp"); return 0; }