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

📄 key_list.cpp

📁 ACE自适配通信环境(ADAPTIVE Communication Environment)是可以自由使用、开放源码的面向对象(OO)框架(Framework)
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// -*- C++ -*-// Key_List.cpp,v 4.63 2005/10/03 13:51:58 jwillemsen Exp// Copyright (C) 1989 Free Software Foundation, Inc.// written by Douglas C. Schmidt (schmidt@cs.wustl.edu)// This file is part of GNU GPERF.// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; either version 2// of the License, or (at your option) any later version.// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.#include "Key_List.h"ACE_RCSID(src, Key_List, "Key_List.cpp,v 4.63 2005/10/03 13:51:58 jwillemsen Exp")#if defined (ACE_HAS_GPERF)#include "ace/Read_Buffer.h"#include "Hash_Table.h"#include "ace/OS_Memory.h"#include "ace/OS_NS_stdio.h"#include "ace/OS_NS_string.h"// Default type for generated code.const char *const Key_List::default_array_type = "char *";// in_word_set return type, by default.const char *const Key_List::default_return_type = "char *";// How wide the printed field width must be to contain the maximum// hash value.int Key_List::field_width = 0;int Key_List::determined_[ACE_STANDARD_CHARACTER_SET_SIZE];// Destructor dumps diagnostics during debugging.Key_List::~Key_List (void){  if (option[DEBUGGING])    this->dump ();  // Free up all the nodes in the list.  while (this->head != 0)    {      List_Node *temp;      // Make sure to delete the linked nodes, as well.      for (List_Node *ptr = this->head->link;           ptr != 0;           ptr = temp)        {          temp = ptr->link;          delete ptr;        }      temp = this->head->next;      delete this->head;      this->head = temp;    }}// Gathers the input stream into a buffer until one of two things occur://// 1. We read a '%' followed by a '%'// 2. We read a '%' followed by a '}'//// The first symbolizes the beginning of the keyword list proper, The// second symbolizes the end of the C source code to be generated// verbatim in the output file.//// I assume that the keys are separated from the optional preceding// struct declaration by a consecutive % followed by either % or }// starting in the first column. The code below uses an expandible// buffer to scan off and return a pointer to all the code (if any)// appearing before the delimiter.char *Key_List::special_input (char delimiter){  int size = 80;  char *buf = 0;  ACE_NEW_RETURN (buf,                  char[size],                  0);  int c;  for (int i = 0; (c = getchar ()) != EOF; i++)    {      if (c == '%')        {          c = getchar ();          if (c == delimiter)            {              // Discard newline...              while ((c = getchar ()) != '\n')                continue;              if (i == 0)                {                  buf[0] = '\0';                  return buf;                }              else                {                  buf[delimiter == '%' && buf[i - 2] == ';'                     ? i - 2                     : i - 1] = '\0';                  return buf;                }            }          else            buf[i++] = '%';        }      else if (i >= size)        {          // Yikes, time to grow the buffer!          char *temp = 0;          ACE_NEW_RETURN (temp,                          char[size *= 2],                          0);          for (int j = 0; j < i; j++)            temp[j] = buf[j];          delete [] buf;          buf = temp;        }      buf[i] = c;    }  return 0;}// Stores any C/C++ source code that must be included verbatim into// the generated code output.char *Key_List::save_include_src (void){  int c = getchar ();  if (c != '%')    ungetc (c, stdin);  else if ((c = getchar ()) != '{')    ACE_ERROR_RETURN ((LM_ERROR,                       "internal error, %c != '{' on line %l in file %N",                       c),                       0);  else    return special_input ('}');  return (char *) "";}// Determines from the input file whether the user wants to build a// table from a user-defined struct, or whether the user is content to// simply use the default array of keys.char *Key_List::array_type (void){  return special_input ('%');}// Sets up the Return_Type, the Struct_Tag type and the Array_Type// based upon various user Options.intKey_List::output_types (void){  if (option[TYPE])    {      array_type_ = array_type ();      if (array_type_ == 0)        // Something's wrong, but we'll catch it later on....        return -1;      else        {          // Yow, we've got a user-defined type...          size_t struct_tag_length = ACE_OS::strcspn (array_type_,                                                      "{\n\0");          if (option[POINTER])      // And it must return a pointer...            {              ACE_NEW_RETURN (return_type,                              char[struct_tag_length + 2],                              -1);              ACE_OS::strncpy (return_type,                               array_type_,                               struct_tag_length);              return_type[struct_tag_length] = '*';              return_type[struct_tag_length + 1] = '\0';            }          ACE_NEW_RETURN (struct_tag,                          char[struct_tag_length + 2],                          -1);          ACE_OS::strncpy (struct_tag,                           array_type_,                           struct_tag_length);          if (struct_tag[struct_tag_length] != ' ')            {              struct_tag[struct_tag_length] = ' ';              struct_tag_length++;            }          struct_tag[struct_tag_length] = '\0';        }    }  else if (option[POINTER])     // Return a char *.    return_type = (char *) Key_List::default_array_type;  return 0;}// Reads in all keys from standard input and creates a linked list// pointed to by Head.  This list is then quickly checked for// ``links,'' i.e., unhashable elements possessing identical key sets// and lengths.intKey_List::read_keys (void){  this->include_src = this->save_include_src ();  if (this->include_src == 0)    return -1;  else if (this->output_types () == -1)    return -1;  else    {      ACE_Read_Buffer input (stdin);      char *buffer = input.read ('\n');      if (buffer == 0)        ACE_ERROR_RETURN ((LM_ERROR,                           "No words in input file, did you forget to prepend %%%%"                           " or use -t accidentally?\n"),                          -1);      // Read in all the keywords from the input file.      else        {          List_Node *temp = 0;          const char *delimiter = option.delimiter ();          ACE_NEW_RETURN (this->head,                          List_Node (buffer,                                     static_cast<int> (ACE_OS::strcspn (buffer,                                                        delimiter))),                          -1);          for (temp = this->head;               (buffer = input.read ('\n'))                 && ACE_OS::strcmp (buffer, "%%");               temp = temp->next)            {              ACE_NEW_RETURN (temp->next,                              List_Node (buffer,                                         static_cast<int> (ACE_OS::strcspn (buffer,                                                            delimiter))),                              -1);              this->total_keys++;            }          // See if any additional source code is included at end of          // this file.          if (buffer)            additional_code = 1;          this->list_len = this->total_keys;          // Make large hash table for efficiency.          Hash_Table table (this->list_len * Key_List::TABLE_MULTIPLE);          List_Node *trail = 0;          // Test whether there are any links and also set the maximum          // length an identifier in the keyword list.          for (temp = head;               temp != 0;               temp = temp->next)            {              List_Node *ptr = table.find (temp, option[NOLENGTH]);              // Check for static key links.  We deal with these by              // building an equivalence class of all duplicate values              // (i.e., links) so that only 1 keyword is              // representative of the entire collection.  This              // *greatly* simplifies processing during later stages              // of the program.              if (ptr == 0)                trail = temp;              else                {                  total_duplicates++;                  list_len--;                  trail->next = temp->next;                  temp->link = ptr->link;                  ptr->link = temp;                  // Complain if user hasn't enabled the duplicate                  // option.                  if (!option[DUP] || option[DEBUGGING])                    ACE_ERROR ((LM_ERROR,                                "Static key link: \"%s\" = \"%s\", with key set \"%s\".\n",                                temp->key,                                ptr->key,                                temp->keysig));                }              // Update minimum and maximum keyword length, if needed.              if (max_key_len < temp->length)                max_key_len = temp->length;              if (min_key_len > temp->length)                min_key_len = temp->length;            }        }      // Exit program if links exists and option[DUP] not set, since      // we can't continue.      if (total_duplicates)        {          if (option[DUP])            {              if (!option[MUTE])                ACE_ERROR_RETURN ((LM_ERROR,                                   "%d input keysigs have identical hash values, examine output carefully...\n",                                   total_duplicates),                                   0);            }          else            ACE_ERROR_RETURN ((LM_ERROR,                               "%d input keysigs have identical hash values,\ntry different key positions or use option -D.\n",                               total_duplicates),                              -1);        }      if (option[ALLCHARS])        option.keysig_size (max_key_len);    }  return 0;}// Recursively merges two sorted lists together to form one sorted// list. The ordering criteria is by frequency of occurrence of// elements in the key set or by the hash value.  This is a kludge,// but permits nice sharing of almost identical code without incurring// the overhead of a function call comparison.List_Node *Key_List::merge (List_Node *list1, List_Node *list2){  if (!list1)    return list2;  else if (!list2)    return list1;  else if (occurrence_sort && list1->occurrence < list2->occurrence           || hash_sort && list1->hash_value > list2->hash_value           || key_sort && ACE_OS::strcmp (list1->key, list2->key) >= 0)    {      list2->next = merge (list2->next, list1);      return list2;    }  else    {      list1->next = merge (list1->next, list2);      return list1;    }

⌨️ 快捷键说明

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