📄 hash.c
字号:
ReturnCode ret; struct Identifier *get; unsigned long hash=Gethash(name); get=scr->hash[hash%scr->hash_size];#ifdef DEBUG hashed=0;#endif while(get) { if( (get->hash==hash) && /* identical hash value! */ !strcmp(get->name, name) && /* identical name! */ (get->flags&(FPL_GLOBAL_SYMBOL|FPL_EXPORT_SYMBOL) || (get->func==scr->func && get->level<=scr->varlevel)) && /* If not global, declared under the *same* function, in this or a lower level! */ (get->flags&FPL_EXPORT_SYMBOL || !strcmp(get->file, scr->prog->name)) /* If not cross-file, the same file! */ ) { /* this is it! */ *ident=get;#ifdef DEBUG if(hashed>max_hashed) max_hashed=hashed;#endif if(get->flags&FPL_EXTERNAL_VARIABLE) { CALL(Hijack(scr, get)); } else if(scr->flags&FPLDATA_ISOLATE && get->flags&FPL_EXPORT_SYMBOL) { /* * Isolated and exported symbol... really? */ if((get->flags&(FPL_FUNCTION|FPL_KEYWORD) == FPL_INSIDE_FUNCTION) || get->flags&FPL_VARIABLE) { /* * Nope, this symbol shouldn't get returned! */ break; } }#ifdef DEBUGMAIL DebugMail(scr, MAIL_IDENTIFIER_ACCESS, 0, get);#endif return FPL_OK; } else if(get->hash<hash) /* we've been searching through all possible alternatives! */ break;#ifdef DEBUG hashed++;#endif get=get->next; } *ident=NULL; return FPLERR_IDENTIFIER_NOT_FOUND;}#ifndef AMIGA /* if not using SAS/C on Amiga */#ifdef VARARG_FUNCTIONSlong fplAddVariableTags(void *anchor, uchar *name, long ID, uchar type, void *defvalue, ...){ va_list tags; long ret;#ifdef SUNOS va_start(tags); /* get parameter list */#else va_start(tags, defvalue); /* get parameter list */#endif ret = fplAddVariable(anchor, name, ID, type, defvalue, (unsigned long *)tags); va_end(tags); return ret;}#elselong PREFIX fplAddVariableTags(void *anchor, uchar *name, long ID, uchar type, void *defvalue, unsigned long tags, ...){ return fplAddVariable(anchor, name, ID, type, defvalue, &tags);}#endif#endif/********************************************************************** * * int fplAddVariable(); * * User frontend to AddIdentifier(). New in version 10! * *****/ReturnCode PREFIX fplAddVariable(AREG(0) struct Data *scr, /* pointer to struct Data */ AREG(1) uchar *name, /* name of variable */ DREG(0) long ID, /* variable ID */ DREG(1) uchar type, /* variable type */ AREG(2) void *defvalue, /* default value */ AREG(3) unsigned long *tags) /* taglist pointer */{ ReturnCode ret; struct Identifier *ident;#ifdef DEBUGMAIL DebugMail(scr, MAIL_FUNCTION, 500, "fplAddVariable");#endif if(!scr) return(FPLERR_ILLEGAL_ANCHOR); GETMEMA(ident, sizeof(struct Identifier)); memset(&ident->data.variable, 0, sizeof(struct fplVariable)); ident->name = name; ident->data.variable.ID = ID; ident->flags = FPL_EXTERNAL_VARIABLE|FPL_GLOBAL_SYMBOL|FPL_EXPORT_SYMBOL| (type == FPL_STRARG? FPL_STRING_VARIABLE:FPL_INT_VARIABLE)| FPL_READONLY; if(type == FPL_INTARG) { GETMEM(ident->data.variable.var.val32, sizeof(long)); ident->data.variable.var.val32[0] = (long) defvalue; } else if(defvalue) { register long len = (long)strlen((uchar *)defvalue); if(len) { GETMEM(ident->data.variable.var.str, sizeof(struct fplStr *)); GETMEM(ident->data.variable.var.str[0], len + sizeof(struct fplStr)); ident->data.variable.var.str[0]->len = len; ident->data.variable.var.str[0]->alloc = len; memcpy(ident->data.variable.var.str[0]->string, defvalue, len); ident->data.variable.var.str[0]->string[len] = '\0'; /* Z-terminate */ } } ident->file = "<user>"; /* Used added! */ ident->func = NULL; /* everywhere! */ ident->level = 0; CALL(AddIdentifier(scr, ident)); return(FPL_OK);}/************************************************************************* * * Hijack(); * * This function gets called whenever an external variable has been selected * by GetIdentifier(). * ******/static ReturnCode INLINE Hijack(struct Data *scr, struct Identifier *ident){ struct fplArgument pass; struct fplMsg *msg; ReturnCode ret; memset(&pass, 0, sizeof(struct fplArgument)); pass.argc=0; pass.name=ident->name; pass.ID=ident->data.variable.ID; pass.key=scr; pass.variable = (void *) (ident->flags&FPL_STRING_VARIABLE? (ident->data.variable.var.str &&ident->data.variable.var.str[0]? ident->data.variable.var.str[0]->string:""): (void *)ident->data.variable.var.val32[0]); CALL(InterfaceCall(scr, &pass, scr->function)); if(ident->flags&FPL_INT_VARIABLE) { /* * Integer variable! */ CALL(GetMessage(scr, FPLMSG_RETURN, &msg)); if(msg && msg->flags&FPLMSG_FLG_INT) { ident->data.variable.var.val32[0]=(long)msg->message[0]; CALL(DeleteMessage(scr, msg)); } } else { /* * String variable! */ CALL(GetMessage(scr, FPLMSG_RETURN, &msg)); if(msg && msg->flags&FPLMSG_FLG_STRING) { if(!ident->data.variable.var.str) { GETMEMA(ident->data.variable.var.str, sizeof(struct fplStr *)); } else if(ident->data.variable.var.str[0]) { FREEA(ident->data.variable.var.str[0]); } ident->data.variable.var.str[0]=(struct fplStr *)msg->message[0]; /* * Make the string to be static always! */ SwapMem(scr, ident->data.variable.var.str[0], MALLOC_STATIC); DeleteMessage(scr, msg); } } return(FPL_OK);}/********************************************************************** * * int InitHash() * * Initialize the hash table. Simple and quick! * *****/struct ShitData { uchar *name; long ID; uchar ret; uchar *format;};struct MoreShitData { uchar *name; long ID; long flags;};static ReturnCode INLINE InitHash(struct Data *scr){ ReturnCode ret; static struct ShitData internal_functions[]={ {"abs", FNC_ABS, 'I', "I"}, {"atoi", FNC_ATOI, 'I', "S"}, {"closelib", FNC_CLOSELIB, 'I', "S"}, /* amiga only */ {"debug", FNC_DEBUG, 'I', "i"}, {"eval", FNC_EVAL, 'I', "S"}, {"exists", FNC_EXISTS, 'I', "Si"}, {"interpret", FNC_INTERPRET, 'I', "S"}, {"itoa", FNC_ITOA, 'S', "I"}, {"itoc", FNC_ITOC, 'S', "I"}, {"joinstr", FNC_JOINSTR, 'S', "s>"}, {"ltostr", FNC_LTOSTR, 'S', "Ii"}, {"openlib", FNC_OPENLIB, 'I', "SI"}, /* amiga only */ {"rename", FNC_RENAME, 'I', "SS"}, {"sprintf", FNC_SPRINTF, 'S', "Sa>"}, {"sscanf", FNC_SSCANF, 'I', "SSa>"}, {"strcmp", FNC_STRCMP, 'I', "SS"}, {"stricmp", FNC_STRICMP, 'I', "SS"}, {"strlen", FNC_STRLEN, 'I', "S"}, {"strncmp", FNC_STRNCMP, 'I', "SSI"}, {"strnicmp", FNC_STRNICMP, 'I', "SSI"}, {"strstr", FNC_STRSTR, 'I', "SSi"}, {"stristr", FNC_STRISTR, 'I', "SSi"}, {"strtol", FNC_STRTOL, 'I', "Si"}, {"substr", FNC_SUBSTR, 'S', "SII"}, }; /* FPL keywords. "else" is not included (treated special). Is is defines as KEYWORD_ELSE */ static struct MoreShitData keywords[]={ {"auto", CMD_AUTO, FPL_KEYWORD_DECLARE}, {"break", CMD_BREAK, 0}, {"case", CMD_CASE, 0}, {"char", CMD_INT, FPL_KEYWORD_DECLARE|FPL_CHAR_VARIABLE}, {"const", CMD_CONST, FPL_KEYWORD_DECLARE}, {"continue", CMD_CONTINUE, 0}, {"default", CMD_DEFAULT, 0}, {"do", CMD_DO, 0}, {"double", CMD_DOUBLE, FPL_IGNORE}, {"enum", CMD_ENUM, FPL_IGNORE}, {"exit", CMD_EXIT, 0}, {"export", CMD_EXPORT, FPL_KEYWORD_DECLARE}, {"float", CMD_FLOAT, FPL_IGNORE}, {"for", CMD_FOR, 0}, {"if", CMD_IF, 0}, {"int", CMD_INT, FPL_KEYWORD_DECLARE}, {"long", CMD_INT, FPL_KEYWORD_DECLARE}, {"register",CMD_REGISTER, FPL_KEYWORD_DECLARE}, {"resize", CMD_RESIZE, 0}, {"return", CMD_RETURN, 0}, {"short", CMD_INT, FPL_KEYWORD_DECLARE|FPL_SHORT_VARIABLE}, {"signed", CMD_SIGNED, FPL_KEYWORD_DECLARE|FPL_IGNORE}, {"static", CMD_STATIC, FPL_KEYWORD_DECLARE}, {"string", CMD_STRING, FPL_KEYWORD_DECLARE}, {"struct", CMD_STRUCT, FPL_IGNORE}, {"switch", CMD_SWITCH, 0}, {"typedef", CMD_TYPEDEF, 0}, {"union", CMD_UNION, FPL_IGNORE}, {"unsigned",CMD_UNSIGNED, FPL_KEYWORD_DECLARE|FPL_IGNORE}, {"void", CMD_VOID, FPL_KEYWORD_DECLARE}, {"volatile",CMD_VOLATILE, FPL_KEYWORD_DECLARE|FPL_IGNORE}, {"while", CMD_WHILE, 0}, }; long i; struct Identifier *ident; GETMEMA(scr->hash, sizeof(struct Identifier *)* scr->hash_size); memset((void *)scr->hash, 0, sizeof(struct Identifier *)*scr->hash_size); /* * The hash table initialization gives us a brilliant chance to bring up * the execution speed even more by inserting the few internal functions * into this same table. The functions will then act *EXACTLY* the same * and we can shorten the code and much easier write internal functions * that return strings... */ for(i=0; i<sizeof(internal_functions)/sizeof(struct ShitData);i++) { GETMEMA(ident, sizeof(struct Identifier)); ident->name=internal_functions[i].name; ident->data.external.ID=internal_functions[i].ID; ident->data.external.ret=internal_functions[i].ret; ident->data.external.format=internal_functions[i].format; ident->flags=FPL_INTERNAL_FUNCTION|FPL_EXPORT_SYMBOL; ident->level=0; ident->func=NULL; /* all functions */ ident->file= "<FPL>"; /* internal */ ret=AddIdentifier(scr, ident); if(ret) break; } for(i=0; i<sizeof(keywords)/sizeof(struct MoreShitData);i++) { GETMEMA(ident, sizeof(struct Identifier)); ident->name=keywords[i].name; ident->data.external.ID=keywords[i].ID; /* dirty enum work! */ ident->flags=FPL_EXPORT_SYMBOL|FPL_KEYWORD|keywords[i].flags; ident->level=0; ident->func=NULL; /* all functions */ ident->file= "<FPL>"; /* internal */ ret=AddIdentifier(scr, ident); if(ret) break; } return(ret);}/********************************************************************** * * int Gethash(); * * Return the hash number for the name received as argument. * *****/static unsigned long INLINE Gethash(uchar *name){ unsigned long hash=0; while(*name) hash=(hash<<1)+*name+++(hash&(1<<31)?-2000000000:0); return(hash);}/********************************************************************** * * void Free(); * * This function frees the resources used by this FPL session. * ***********/void PREFIX fplFree(AREG(0) struct Data *scr){ struct Data onstack;#ifdef AMIGA long retval;#endif#ifdef DEBUGMAIL DebugMail(scr, MAIL_FUNCTION, 500, "fplFree");#endif onstack=*scr; /* copy the entire struct */ scr=&onstack; /* use the `stack-struct' */ DelProgram(scr, NULL); /* remove all programs from memory, some might be Lock()'ed! */#ifdef AMIGA /* only amiga supports funclibs! */ CloseLib(scr, NULL, TRUE, &retval); /* force close of all funclibs */#endif FREEALL(); FREEALLA();}/********************************************************************** * * int DelIdentifier() * * Delete an identifier from the hash table. Specify 'name' or 'ident'. * ******/ReturnCode REGARGSDelIdentifier(struct Data *scr, uchar *name, /* only needed if 'ident' is NULL! */ struct Identifier *ident){ ReturnCode ret=FPL_OK; long i; struct fplVariable *var; if(!ident) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -