📄 macedon-transition.c
字号:
//Copyright (c) 2004, Charles Killian, Adolfo Rodriguez, Dejan Kostic, Sooraj Bhat, and Amin Vahdat//All rights reserved.////Redistribution and use in source and binary forms, with or without//modification, are permitted provided that the following conditions are met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in// the documentation and/or other materials provided with the// distribution.// * Neither the names of Duke University nor The University of// California, San Diego, nor the names of its contributors// may be used to endorse or promote products derived from// this software without specific prior written permission.////THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"//AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE//DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE//USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE./* macedon-transition.c *//* * For MACEDON code generation * * Adolfo Rodriguez *//* includes */#include <fnmatch.h>#include <stdio.h>#include <string.h> /* for strcmp(), strdup() */#include "macedon-conv.h"#include "macedon-conv-utils.h"/* imports */extern char *protocol_name;extern FILE *hfile, *cfile, *cfilefuncs, *cfile2;extern node_type *my_node_types;extern message *my_messages;extern transport *my_transports;extern neighbor_type *my_neighbor_types;extern declare *my_periphs;extern declare *my_locals;extern state *my_states;extern timer *my_timers;extern constant *my_constants;extern object_replace *my_replaces;extern api_demux* apidemux;extern msg_demux* msglist;extern char *base_name;extern int API_specified[API_num_types];extern int trans_API;extern int trans_API_index;extern int trans_locking;extern int init_func;extern int tracing;char* expr_to_human_readable(char* expr){ char ch; char *temp,*res; if (strcmp(expr,"any")==0 || strcmp(expr,"*")==0) return strdup("any"); res = (char*)malloc(128); temp = res; while (ch = *expr) { switch (ch) { case '!': sprintf(temp,"%s","not_"); temp += 4; break; case '(': sprintf(temp,"%s","op_"); temp += 3; break; case '|': sprintf(temp,"%s","or_"); temp += 3; break; case ')': sprintf(temp,"%s","cp_"); temp += 3; break; case '?': sprintf(temp,"%s","qm_"); temp += 3; break; case '*': sprintf(temp,"%s","star_"); temp += 5; break; default: while (ch && (isalnum(ch) || ch == '_')) { *temp++ = ch; ch = *++expr; } *temp++ = '_'; expr--; break; } expr++; } *--temp = 0; return res;}void transition_locking (char *type){ if (!strcmp(type, "none")) trans_locking = LOCK_NONE; else if (!strcmp(type, "read")) trans_locking = LOCK_READ; else if (!strcmp(type, "write")) trans_locking = LOCK_WRITE; else trans_locking = LOCK_UNSPECIFIED;}void add_transition(char *instate, char *func, char *name){ int i; state *temps; char * temp ; char *state ; char *base_state; char *timer_name; char *real_timer_name; char real_name[100]; timer *tempt; timer_demux *temptd; api_demux *tempad; declare *tempp; node_type *tempnt; message *mymsg; FILE *outcfile; int flags_notted_tran; int the_first; char *temp_str; msg_demux* msgd;#ifdef GEN_TRACE printf("Adding transition %s %s %s\n", instate, func, name); fflush(NULL);#endif /** * Process the state expression. The human-readable name * goes in 'state', the expression stays in 'instate' * 'base_state' is unused (Jul 23 2003... Sooraj) * pattern matching is done later in this function * and in end_agent(), too. **/ state = expr_to_human_readable(instate); /** this block MUST come after the call to * expr_to_human_readable() */ if (instate[0]=='!') { if (instate[1] != '(') { temp_str = (char*)malloc(400); sprintf(temp_str,"!(%s)",instate+1); instate = temp_str; } } else { temp_str = (char*)malloc(400); sprintf(temp_str,"@(%s)",instate); instate = temp_str; } if (strncmp(func, "recv", 4) == 0 || strncmp(func, "forward", 7) == 0) { int recv_flag; if (strncmp(func, "recv", 4) == 0) { fprintf(hfile, " void %s_%s_%s(Packet *);\n", state, func, name); #ifdef PROFILE_AGENTS fprintf(hfile, " int %s_%s_%s_count;\n", state, func, name); fprintf(hfile, " double %s_%s_%s_total;\n", state, func, name); #endif outcfile = cfile; recv_flag = 1; } else { fprintf(hfile, " int %s_%s_%s(Packet *);\n", state, func, name); #ifdef PROFILE_AGENTS fprintf(hfile, " int %s_%s_%s_count;\n", state, func, name); fprintf(hfile, " double %s_%s_%s_total;\n", state, func, name); #endif outcfile = cfile2; recv_flag = 3; } sprintf(real_name, "%s_message_%s", protocol_name, name); mymsg = lookup_message(real_name); if (mymsg==0) { printf("Error in finding message %s specified in transition.\n", real_name); exit(46); } fprintf(outcfile, " if(!processed && recv_hdr%s->%s_mf_.mh_type_ == %s_message_%s && (\n", protocol_name, protocol_name, protocol_name, name); if (strcmp(state,"any")==0) { fprintf(outcfile,"true"); } else { the_first = 1; temps = my_states; while (temps) { if (fnmatch(instate,temps->base_state_name,FNM_EXTMATCH)==0) { if (!the_first) fprintf(outcfile, " ||"); else the_first = 0; fprintf(outcfile, " fsm == %s ",temps->state_name); } temps = temps->next; } } fprintf(outcfile,"))\n"); fprintf(outcfile, " {\n"); fprintf(outcfile, " processed = 1;\n"); if (tracing) fprintf(outcfile, " dump_packet(pkt, 0, %d);\n", recv_flag); if (trans_locking == LOCK_NONE) { // no locking at all } else if (trans_locking == LOCK_READ) { // read locking semantics fprintf(outcfile, " Lock_Read();\n"); } else if (trans_locking == LOCK_WRITE || trans_locking == LOCK_UNSPECIFIED) { // write locking semantics fprintf(outcfile, " Lock_Write();\n"); } #ifdef PROFILE_AGENTS fprintf(outcfile, " double _starttime = Scheduler::instance().clock();\n");#endif if (strncmp(func, "recv", 4) == 0) fprintf(outcfile, " %s_%s_%s(pkt);\n", state, func, name); else { fprintf(outcfile, " retval = %s_%s_%s(pkt);\n", state, func, name); if (tracing) { fprintf(outcfile, " if(!retval)\n"); fprintf(outcfile, " dump_packet(pkt, 0, 2);\n"); } } msgd = (msg_demux*)malloc(sizeof(msg_demux)); msgd->next = msglist; msgd->msgfunc = (char*) malloc(strlen(state)+strlen(func)+strlen(name)+3); sprintf(msgd->msgfunc, "%s_%s_%s", state, func, name); msglist = msgd;#ifdef PROFILE_AGENTS fprintf(outcfile, " %s_%s_%s_count++;\n", state, func, name); fprintf(outcfile, " %s_%s_%s_total+=Scheduler::instance().clock()-_starttime;\n",state, func, name);#endif if (trans_locking == LOCK_NONE) { // no locking at all } else { // locking fprintf(outcfile, " Unlock();\n"); } fprintf(outcfile, " }\n"); fprintf(outcfile, "\n"); if (strncmp(func, "recv", 4) == 0) fprintf(cfilefuncs, "void %s_Agent::%s_%s_%s(Packet *pkt)\n", protocol_name, state, func, name); else fprintf(cfilefuncs, "int %s_Agent::%s_%s_%s(Packet *pkt)\n", protocol_name, state, func, name); fprintf(cfilefuncs, "{\n"); fprintf(cfilefuncs, " double curtime = Scheduler::instance().clock();\n");#ifdef ALLINONEHDR fprintf(cfilefuncs, " unpack_pkt();\n"); #else fprintf(cfilefuncs, " unpack_pkt(%s);\n", name); #endif } else if (strncmp(func, "timer", 5) == 0) { timer_name = name; real_timer_name = conv_name_timer(timer_name); tempt = lookup_timer(real_timer_name); temptd = (timer_demux *) malloc (sizeof(timer_demux)); temptd->state = (char *) malloc (strlen(instate)+1); /** send it the expr, to evaluate later (in end_agent()) **/ sprintf(temptd->state, "%s", instate); temptd->locking = trans_locking; temptd->func = (char *) malloc (strlen(state)+strlen(func)+strlen(name)+3); sprintf(temptd->func, "%s_%s_%s", state, func, timer_name); temptd->next = tempt->demux; tempt->demux = temptd; fprintf(hfile, " void %s_%s_%s();\n", state, func, timer_name); #ifdef PROFILE_AGENTS fprintf(hfile, " int %s_%s_%s_count;\n", state, func, name); fprintf(hfile, " double %s_%s_%s_total;\n", state, func, name); #endif fprintf(cfilefuncs, "void %s_Agent::%s_%s_%s()\n", protocol_name, state, func, timer_name); fprintf(cfilefuncs, "{\n"); fprintf(cfilefuncs, " double curtime = Scheduler::instance().clock();\n"); } else if (strncmp(func, "API", 3) == 0) { for (i=0; i<API_num_types; i++) { if (strcmp(name, API_types[i])==0) { API_specified[i]=1; fprintf(hfile, " %s %s_%s_%s%s;\n", API_returns[i], state, func, name, API_protoparams[i]); #ifdef PROFILE_AGENTS fprintf(hfile, " int %s_%s_%s_count;\n", state, func, name); fprintf(hfile, " double %s_%s_%s_total;\n", state, func, name); #endif fprintf(cfilefuncs, "%s %s_Agent::%s_%s_%s%s\n", API_returns[i], protocol_name, state, func, name, API_protoparams[i]); tempad = (api_demux *) malloc (sizeof(api_demux)); tempad->state = (char *) malloc (strlen(instate)+1); /** send it the expr, to evaluate later (in end_agent()) **/ sprintf(tempad->state, "%s", instate); tempad->func = (char *) malloc (strlen(state)+strlen(func)+strlen(name)+strlen(API_params[i])+3); sprintf(tempad->func, "%s_%s_%s%s", state, func, name, API_params[i]); tempad->func2 = (char *) malloc (strlen(state)+strlen(func)+strlen(name)+3); sprintf(tempad->func2, "%s_%s_%s", state, func, name); tempad->api = (char *) malloc (strlen(name)+2); sprintf(tempad->api, "%s", name); tempad->next = apidemux; tempad->API_index = i; tempad->locking = trans_locking; apidemux = tempad; break; } } if (i==API_num_types) // ran off the end { printf("Error: Specified API function %s, but that is not part of MACEDON API.\n", name); exit(6); } fprintf(cfilefuncs, "{\n"); trans_API = 1; trans_API_index = i; /* if (trans_locking == LOCK_NONE) { // no locking at all */ /* } */ /* else if (trans_locking == LOCK_READ) { // read locking semantics */ /* fprintf(cfilefuncs, " Lock_Read();\n"); */ /* } */ /* else if (trans_locking == LOCK_WRITE) { // write locking semantics */ /* fprintf(cfilefuncs, " Lock_Write();\n"); */ /* } */ /* else { // unspecified, take default behavior */ /* if (API_sendsdata[i] == 1) { */ /* fprintf(cfilefuncs, " if (size == -1) return -1;\n"); */ /* if(API_needslocking[i] == 1) { */ /* fprintf(cfilefuncs, " Lock_Read();\n"); */ /* } */ /* } */ /* else { */ /* if(API_needslocking[i] == 1) { */ /* fprintf(cfilefuncs, " Lock_Write();\n"); */ /* } */ /* } */ /* } */ if (API_sendsdata[i] == 1) fprintf(cfilefuncs, " int return_code = 0;\n"); fprintf(cfilefuncs, " double curtime = Scheduler::instance().clock();\n"); if (strcmp(name, "init")==0) { if (!base_name) { transport *temptr = my_transports; while (temptr) { if (temptr->type) fprintf(cfilefuncs, " %s->register_receiver(this, (tr_handler)&%s_Agent::recv_from_pipe, (er_handler)&%s_Agent::macedon_upcall_ext);\n", temptr->over, protocol_name, protocol_name); temptr = temptr->next; } } init_func=1; tempp = my_periphs; while (tempp) { tempnt = my_node_types; while (tempnt) { if (strcmp(tempp->name, tempnt->simple_name) == 0 && tempp->exported) { fprintf(cfilefuncs, " if (here_.addr_ == %s)\n", tempp->name); fprintf(cfilefuncs, " node_type = %s;\n", tempnt->type_name); } tempnt = tempnt->next; } tempp = tempp->next; } } } else { fprintf(hfile, " void %s_%s_%s();\n", state, func, name); fprintf(cfilefuncs, "void %s_Agent::%s_%s_%s()\n", protocol_name, state, func, name); fprintf(cfilefuncs, "{\n"); fprintf(cfilefuncs, " double curtime = Scheduler::instance().clock();\n"); fprintf(stderr, "Warning: Added transition of unknown type. HOW DID I GET HERE? Pls fill out a bug report!\n"); } return;}void done_transition(){ declare *temp; if (trans_API) { /* if (trans_locking == LOCK_NONE) { // no locking at all */ /* } */ /* else if (trans_locking == LOCK_WRITE || */ /* trans_locking == LOCK_READ || */ /* API_needslocking[trans_API_index] == 1) { // locking semantics */ /* fprintf(cfilefuncs, " Unlock();\n"); */ /* } */ if (API_sendsdata[trans_API_index] == 1) { fprintf(cfilefuncs, " return return_code;\n"); } } trans_locking = LOCK_UNSPECIFIED; // reset locking flag if (init_func==1) { init_func=0; } fprintf(cfilefuncs, "}\n"); fprintf(cfilefuncs, "\n"); temp = my_locals; while (temp) { my_locals = temp->next; free (temp->type); free (temp->name); free (temp); temp = my_locals; } trans_API=0; return;} void add_prototype(char* type, char* funcname){#ifdef GEN_TRACE printf("Adding routine %s %s\n", type, funcname); fflush(NULL);#endif fprintf(hfile, "%s %s", type, funcname); fprintf(cfilefuncs, "%s %s_Agent::%s", type, protocol_name, funcname);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -