retcode.c
来自「Sun公司Dream项目」· C语言 代码 · 共 358 行
C
358 行
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the "License"). You may not use this file except
* in compliance with the License.
*
* You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If
* applicable, add the following below this CDDL HEADER,
* with the fields enclosed by brackets "[]" replaced
* with your own identifying information:
* Portions Copyright [yyyy]
* [name of copyright owner]
*/
/*
* $(@)RetCode.c $Revision: 1.2 $ $Date: 2006/07/15 00:02:34 $
*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*/
/*
* Copyright (c) 1996 by Sun Microsystems, Inc.
*/
#pragma ident "@(#)RetCode.c 1.6 99/08/26 SMI"
/*
* RetCode.c -- RetCode handling routines
*/
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <thread.h>
#include <synch.h>
#include <stdio.h>
#include "cobjs/ArrayOf.h"
#include "cobjs/Log.h"
#include "cobjs/Macros.h"
#include "cobjs/Types.h"
#include "cobjs/RetCode.h"
/*
* id 0 is reserved for syscall errors
* id 1 is reserved for client side errors
*/
#define BASE_ID 2
#define FIELD_SIZE 30
/*************************************************************************
* Private class data
*************************************************************************/
typedef struct RetCodeEntry {
const char *className;
RetCodeId id;
Boolean hasTable;
RetCodeTable *table;
RetCodeFunc func;
} RetCodeEntry;
static ArrayOf retCodeArray;
static u16 currentId = BASE_ID;
static thread_key_t retCodeBufKey;
static mutex_t retCodeMutex;
static Boolean retCodeIsFrozen = FALSE;
static char fill[] = " ";
static int fillSize = sizeof(fill) - 1;
static RetCodeTable retCodeGlobal[] = {
{RETCODE_FAILED, "FAILED", "unspecified failure"},
{0, NULL}
};
/*************************************************************************
* OBJECT Template Class Methods
*************************************************************************/
static void
retCodeInit(void)
{
RetCodeEntry entry;
ABORT_IF_ERRNO(mutex_init(&retCodeMutex, USYNC_THREAD, 0));
ABORT_IF_ERRNO(thr_keycreate(&retCodeBufKey, free));
retCodeArray = NEW_ARRAY(RetCodeEntry);
entry.className = strdup("RetCode Global");
entry.id = currentId++;
entry.hasTable = TRUE;
entry.table = retCodeGlobal;
entry.func = NULL;
arrayOfItemAt(retCodeArray, RetCodeEntry, entry.id) = entry;
}
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
#pragma init(retCodeInit)
#elif defined (__GNUC__)
static void retCodeInit(void) __attribute__ ((constructor));
#endif
static void
retCodeFini(void)
{
int i;
int len = arrayOfLength(retCodeArray);
for (i = BASE_ID; i < len; i++) {
free((void *)arrayOfItemAt(retCodeArray, RetCodeEntry, i).className);
}
arrayOfFree(retCodeArray);
}
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
#pragma fini(retCodeFini)
#elif defined(__GNUC__)
static void retCodeFini(void) __attribute__ ((destructor));
#endif
RetCodeId
retCodeRegisterWithTable(const char *className, RetCodeTable *table)
{
RetCodeEntry entry;
RetCodeTable *rctp;
int i;
CHECK_IF_ERRNO(mutex_lock(&retCodeMutex));
if (retCodeIsFrozen) {
ABORT("retCode Frozen");
}
for (i = BASE_ID; i < arrayOfLength(retCodeArray); i++) {
RetCodeEntry *entryp = (RetCodeEntry*)arrayOfItemAtByPtr(retCodeArray, i);
if (strcmp(className, entryp->className) == 0) {
if (! entryp->hasTable || table != entryp->table) {
ABORT("redefinition of retCode");
}
CHECK_IF_ERRNO(mutex_unlock(&retCodeMutex));
return entryp->id;
}
}
entry.className = strdup(className);
entry.id = currentId++;
entry.hasTable = TRUE;
entry.table = table;
entry.func = NULL;
for (rctp = table; rctp->msg != NULL; rctp++) {
if (rctp->localCode == 0 || rctp->localCode > 0xffff) {
logLibPrint(cobjs_TEXT_DOMAIN, "invalid RetCodeTable: %s\n",
className);
ABORT("invalid table");
}
}
arrayOfItemAt(retCodeArray, RetCodeEntry, entry.id) = entry;
CHECK_IF_ERRNO(mutex_unlock(&retCodeMutex));
return entry.id;
}
RetCodeId
retCodeRegisterWithFunc(const char *className, RetCodeFunc func)
{
RetCodeEntry entry;
int i;
CHECK_IF_ERRNO(mutex_lock(&retCodeMutex));
if (retCodeIsFrozen) {
ABORT("retCode Frozen");
}
for (i = BASE_ID; i < arrayOfLength(retCodeArray); i++) {
RetCodeEntry *entryp = (RetCodeEntry*)arrayOfItemAtByPtr(retCodeArray, i);
if (strcmp(className, entryp->className) == 0) {
ASSERT(!entryp->hasTable);
CHECK_IF_ERRNO(mutex_unlock(&retCodeMutex));
return entryp->id;
}
}
entry.className = strdup(className);
entry.id = currentId++;
entry.hasTable = FALSE;
entry.table = NULL;
entry.func = func;
arrayOfItemAt(retCodeArray, RetCodeEntry, entry.id) = entry;
CHECK_IF_ERRNO(mutex_unlock(&retCodeMutex));
return entry.id;
}
const char *
retCodeMsg(RetCode retCode, char *buf, size_t buflen)
{
RetCodeEntry *entryp;
RetCodeId id;
RetCodeTable *rctp;
u16 localCode;
if (retCode == RETCODE_SUCCESS) {
return "Success";
}
id = retCode >> 16;
localCode = retCode & 0xffff;
if (buf == NULL || buflen < 80) {
buflen = 80;
if (thr_getspecific(retCodeBufKey, (void **) &buf) != 0
|| buf == NULL) {
buf = NEW(char, buflen);
ABORT_IF_ERRNO(thr_setspecific(retCodeBufKey, buf));
}
}
if (id == 0 || id > (unsigned) arrayOfLength(retCodeArray)) {
(void) sprintf(buf, "Unregistered Return Code %d:%d", id, localCode);
return buf;
}
entryp = (RetCodeEntry*)arrayOfItemAtByPtr(retCodeArray, id);
if (!entryp->hasTable) {
return (*entryp->func) (localCode, buf, buflen);
}
for (rctp = entryp->table; rctp->msg != NULL; rctp++) {
if ((rctp->localCode & 0xffff) == localCode) {
(void) sprintf(buf, "%.30s: %s", entryp->className, rctp->msg);
return buf;
}
}
(void) sprintf(buf, "%.30s: Unknown return code: %d", entryp->className,
localCode);
return buf;
}
void
retCodeDumpNames(const char *prefix, RetCodeDumpFunc func)
{
int nClasses = arrayOfLength(retCodeArray);
char buf[128];
RetCodeId id;
int fieldSize = FIELD_SIZE - strlen(prefix);
retCodeIsFrozen = TRUE;
for (id = BASE_ID; id < nClasses; id++) {
RetCodeEntry *entryp = (RetCodeEntry*) arrayOfItemAtByPtr(retCodeArray, id);
if (entryp->hasTable) {
RetCodeTable *rctp;
(*func)("/*");
(void) snprintf(buf, sizeof(buf), " * Errors for class %s",
entryp->className);
(*func)(buf);
(*func)(" */");
for (rctp = entryp->table; rctp->msg != NULL; rctp++) {
int len;
int fillLen;
int fillPoint;
if (rctp->codeName == NULL) {
continue;
}
fillLen = fieldSize - strlen(rctp->codeName);
if (fillLen < 0) fillLen = 0;
fillPoint = fillSize - fillLen;
if (fillPoint < 0) fillPoint = 0;
len = snprintf(buf, sizeof(buf) - 1,
"%s%s%s = 0x%06lx, /* %s */",
prefix, rctp->codeName, &fill[fillPoint],
(entryp->id << 16) | (rctp->localCode & 0xffff),
rctp->msg);
if (len > sizeof(buf) - 1) {
ABORT("buf overflow");
}
(*func)(buf);
}
}
}
}
void
retCodeDumpMessages(const char *prefix, RetCodeDumpFunc func)
{
int nClasses = arrayOfLength(retCodeArray);
char buf[128];
RetCodeId id;
int fieldSize = FIELD_SIZE - strlen(prefix);
retCodeIsFrozen = TRUE;
for (id = BASE_ID; id < nClasses; id++) {
RetCodeEntry *entryp = (RetCodeEntry*)arrayOfItemAtByPtr(retCodeArray, id);
if (entryp->hasTable) {
RetCodeTable *rctp;
(*func)("/*");
(void) snprintf(buf, sizeof(buf), " * Errors for class %s",
entryp->className);
(*func)(buf);
(*func)(" */");
for (rctp = entryp->table; rctp->msg != NULL; rctp++) {
int len;
int fillLen;
int fillPoint;
if (rctp->codeName == NULL) {
continue;
}
fillLen = fieldSize - strlen(rctp->codeName);
if (fillLen < 0) fillLen = 0;
fillPoint = fillSize - fillLen;
if (fillPoint < 0) fillPoint = 0;
len = snprintf(buf, sizeof(buf) - 1, "{%s%s,%s \"%s\"},",
prefix, rctp->codeName, &fill[fillPoint],
rctp->msg);
if (len > sizeof(buf) - 1) {
ABORT("buf overflow");
}
(*func)(buf);
}
}
}
}
void
retCodeFreeze(void)
{
retCodeIsFrozen = TRUE;
}
RetCode
retCodeFor(char *className, u32 localCode)
{
int i;
ASSERT((localCode >> 16) == 0);
for (i = BASE_ID; i < arrayOfLength(retCodeArray); i++) {
RetCodeEntry *entryp = (RetCodeEntry*)arrayOfItemAtByPtr(retCodeArray, i);
if (strcmp(className, entryp->className) == 0) {
return RetCode(entryp->id << 16 | localCode);
}
}
/*
* Intentionally blow up
*/
ASSERT(className == NULL);
return RetCode(1);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?