00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #ifndef _WIN32
00039 #include <strings.h>
00040 #else
00041 #define strcasecmp(a, b) \
00042   _stricmp(a, b)
00043 #endif
00044 #include "include/fipa_acl.h"
00045 #include "include/mc_error.h"
00046 #include "include/macros.h"
00047 
00048 #define FREEMEM(x) \
00049   if (x != NULL) free(x)
00050 
00051 
00052 fipa_acl_message_t* fipa_acl_message_New(void)
00053 {
00054   fipa_acl_message_t* acl;
00055   acl = (fipa_acl_message_t*)malloc(sizeof(fipa_acl_message_t));
00056   memset(acl, 0, sizeof(fipa_acl_message_t));
00057   return acl;
00058 }
00059 
00060 int fipa_acl_message_Destroy(fipa_acl_message_t* message)
00061 {
00062 
00063   if (message == NULL) return 0;
00064   fipa_agent_identifier_Destroy(message->sender);
00065   fipa_agent_identifier_set_Destroy(message->receiver);
00066   fipa_agent_identifier_set_Destroy(message->reply_to);
00067   fipa_string_Destroy(message->content);
00068   fipa_expression_Destroy(message->language);
00069   fipa_expression_Destroy(message->encoding);
00070   fipa_expression_Destroy(message->ontology);
00071   fipa_word_Destroy(message->protocol);
00072   fipa_expression_Destroy(message->conversation_id);
00073   fipa_expression_Destroy(message->reply_with);
00074   fipa_expression_Destroy(message->in_reply_to);
00075   fipa_DateTime_Destroy(message->reply_by);
00076   
00077   free(message);
00078   return 0;
00079 }
00080 
00081 fipa_acl_message_t* fipa_acl_message_Copy(fipa_acl_message_t* src)
00082 {
00083   fipa_acl_message_t* copy;
00084   if (src == NULL) return NULL;
00085   copy = fipa_acl_message_New();
00086   copy->performative = src->performative;
00087   copy->sender = fipa_agent_identifier_Copy(src->sender);
00088   copy->receiver = fipa_agent_identifier_set_Copy(src->receiver);
00089   copy->reply_to = fipa_agent_identifier_set_Copy(src->reply_to);
00090   copy->content = fipa_string_Copy(src->content);
00091   copy->language = fipa_expression_Copy(src->language);
00092   copy->encoding = fipa_expression_Copy(src->encoding);
00093   copy->ontology = fipa_expression_Copy(src->ontology);
00094   copy->protocol = fipa_word_Copy(src->protocol);
00095   copy->conversation_id = fipa_expression_Copy(src->conversation_id);
00096   copy->reply_with = fipa_expression_Copy(src->reply_with);
00097   copy->in_reply_to = fipa_expression_Copy(src->in_reply_to);
00098   copy->reply_by = fipa_DateTime_Copy(src->reply_by);
00099 
00100   return copy;
00101 }
00102 
00103 
00104 fipa_message_string_t* fipa_message_string_New(void)
00105 {
00106   fipa_message_string_t* str;
00107   str = (fipa_message_string_t*)malloc(sizeof(fipa_message_string_t));
00108   memset(str, 0, sizeof(fipa_message_string_t));
00109   return str;
00110 }
00111 
00112 int fipa_message_string_Destroy(fipa_message_string_t* message)
00113 {
00114   if (message == NULL) return 0;
00115   if (message->message != NULL) {
00116     free(message->message);
00117   }
00118   free(message); 
00119   return 0;
00120 }
00121 
00122 fipa_message_string_t* fipa_message_string_Copy(fipa_message_string_t* src)
00123 {
00124   fipa_message_string_t* copy;
00125   if (src == NULL) return NULL;
00126   copy->message = strdup(src->message);
00127   copy->parse = copy->message + (src->parse - src->message);
00128   return copy;
00129 }
00130 
00131 
00132 fipa_url_sequence_t* fipa_url_sequence_New(void)
00133 {
00134   fipa_url_sequence_t* sequence;
00135   sequence = (fipa_url_sequence_t*)malloc(sizeof(fipa_url_sequence_t));
00136   memset(sequence, 0, sizeof(fipa_url_sequence_t));
00137   return sequence;
00138 }
00139 
00140 int fipa_url_sequence_Destroy(fipa_url_sequence_t* sequence)
00141 {
00142   int i;
00143   if (sequence == NULL) return 0;
00144   for (i = 0; i < sequence->num; i++) {
00145     fipa_url_Destroy(sequence->urls[i]);
00146   }
00147   free(sequence->urls); 
00148   free(sequence);
00149   return 0;
00150 }
00151 
00152 fipa_url_sequence_t* fipa_url_sequence_Copy(fipa_url_sequence_t* src)
00153 {
00154   int i;
00155   fipa_url_sequence_t* copy;
00156   if (src == NULL) return NULL;
00157   copy = fipa_url_sequence_New();
00158   copy->num = src->num;
00159   copy->urls = (fipa_url_t**)malloc(
00160       sizeof(fipa_url_t*) * src->num);
00161   for( i = 0; i < src->num; i++) {
00162     copy->urls[i] = fipa_url_Copy(src->urls[i]);
00163   }
00164   return copy;
00165 }
00166 
00167 
00168 fipa_agent_identifier_set_t* fipa_agent_identifier_set_New(void)
00169 {
00170   fipa_agent_identifier_set_t* set;
00171   set = (fipa_agent_identifier_set_t*)malloc(sizeof(fipa_agent_identifier_set_t));
00172   memset(set, 0, sizeof(fipa_agent_identifier_set_t));
00173   return set;
00174 }
00175 
00176 int fipa_agent_identifier_set_Destroy(fipa_agent_identifier_set_t* idset)
00177 {
00178   int i;
00179   if (idset == NULL) return 0;
00180   for(i = 0; i < idset->num; i++) {
00181     fipa_agent_identifier_Destroy(idset->fipa_agent_identifiers[i]);
00182   }
00183   free(idset->fipa_agent_identifiers); 
00184   free(idset);
00185   return 0;
00186 }
00187 
00188 fipa_agent_identifier_set_t* fipa_agent_identifier_set_Copy(
00189     fipa_agent_identifier_set_t* src)
00190 {
00191   int i;
00192   fipa_agent_identifier_set_t* copy;
00193 
00194   if (src == NULL) { return NULL; }
00195   copy = fipa_agent_identifier_set_New();
00196   copy->num = src->num;
00197   copy->retain_order = src->retain_order;
00198   copy->fipa_agent_identifiers = (fipa_agent_identifier_t**)malloc(
00199       sizeof(fipa_agent_identifier_t*) * src->num);
00200   for(i = 0; i < src->num; i++) {
00201     copy->fipa_agent_identifiers[i] = fipa_agent_identifier_Copy(
00202         src->fipa_agent_identifiers[i]);
00203   }
00204 
00205   return copy;
00206 }
00207 
00208 
00209 fipa_agent_identifier_t* fipa_agent_identifier_New(void)
00210 {
00211   fipa_agent_identifier_t* id;
00212   id = (fipa_agent_identifier_t*)malloc(sizeof(fipa_agent_identifier_t));
00213   memset(id, 0, sizeof(fipa_agent_identifier_t));
00214   return id;
00215 }
00216 
00217 int fipa_agent_identifier_Destroy(fipa_agent_identifier_t* id)
00218 {
00219   if (id == NULL) return 0;
00220   if (id->name != NULL) {
00221     free(id->name);
00222   }
00223   fipa_url_sequence_Destroy(id->addresses);
00224   fipa_agent_identifier_set_Destroy(id->resolvers);
00225   free(id); 
00226   return 0;
00227 }
00228 
00229 fipa_agent_identifier_t* fipa_agent_identifier_Copy(fipa_agent_identifier_t* src)
00230 {
00231   fipa_agent_identifier_t* copy;
00232   if (src == NULL) return NULL;
00233   copy = fipa_agent_identifier_New();
00234   copy->name = strdup(src->name);
00235   copy->addresses = fipa_url_sequence_Copy(src->addresses);
00236   copy->resolvers = fipa_agent_identifier_set_Copy(src->resolvers);
00237   return copy;
00238 }
00239 
00240 
00241 fipa_expression_t* fipa_expression_New(void)
00242 {
00243   fipa_expression_t* expr;
00244   expr = (fipa_expression_t*)malloc(sizeof(fipa_expression_t));
00245   memset(expr, 0, sizeof(fipa_expression_t));
00246   return expr;
00247 }
00248 
00249 int fipa_expression_Destroy(fipa_expression_t* expr)
00250 {
00251   int i;
00252   if (expr == NULL) return 0;
00253   switch (expr->type) {
00254     case FIPA_EXPR_WORD:
00255       fipa_word_Destroy(expr->content.word);
00256       break;
00257     case FIPA_EXPR_STRING:
00258       fipa_string_Destroy(expr->content.string);
00259       break;
00260     case FIPA_EXPR_NUMBER:
00261       fipa_number_Destroy(expr->content.number);
00262       break;
00263     case FIPA_EXPR_DATETIME:
00264       fipa_DateTime_Destroy(expr->content.datetime);
00265       break;
00266     case FIPA_EXPR_EXPRESSION:
00267       if (expr->content.expression == NULL) break;
00268       for (i = 0; expr->content.expression[i] != NULL; i++) {
00269         fipa_expression_Destroy(expr->content.expression[i]);
00270       }
00271       FREEMEM(expr->content.expression);
00272       break;
00273     default:
00274       break;
00275   }
00276   free(expr);
00277   return 0;
00278 }
00279 
00280 fipa_expression_t* fipa_expression_Copy(fipa_expression_t* src)
00281 {
00282   int i, num;
00283   fipa_expression_t* copy;
00284   if (src == NULL) return NULL;
00285   copy = fipa_expression_New();
00286   copy->type = src->type;
00287   switch(src->type) {
00288     case FIPA_EXPR_WORD:
00289       copy->content.word = fipa_word_Copy(src->content.word);
00290       break;
00291     case FIPA_EXPR_STRING:
00292       copy->content.string = fipa_string_Copy(src->content.string);
00293       break;
00294     case FIPA_EXPR_NUMBER:
00295       copy->content.number = fipa_number_Copy(src->content.number);
00296       break;
00297     case FIPA_EXPR_DATETIME:
00298       copy->content.datetime = fipa_DateTime_Copy(src->content.datetime);
00299       break;
00300     case FIPA_EXPR_EXPRESSION:
00301       
00302       for(i = 0; src->content.expression[i] != NULL; i++);
00303       
00304       num = i;
00305       copy->content.expression = (fipa_expression_t**)malloc(
00306           sizeof(fipa_expression_t*) * (num + 1));
00307       for(i = 0; i < num; i++) {
00308         copy->content.expression[i] = fipa_expression_Copy(
00309             src->content.expression[i] );
00310       }
00311       copy->content.expression[num] = NULL;
00312       break;
00313     default:
00314       fipa_expression_Destroy(copy);
00315       return NULL;
00316   }
00317   return copy;
00318 }
00319       
00320 
00321 fipa_word_t* fipa_word_New(void)
00322 {
00323   fipa_word_t* word;
00324   word = (fipa_word_t*)malloc(sizeof(fipa_word_t));
00325   memset(word, 0, sizeof(fipa_word_t));
00326   return word;
00327 }
00328 
00329 int fipa_word_Destroy(fipa_word_t* word)
00330 {
00331   if (word == NULL) return 0;
00332   if (word->content != NULL) {
00333     free( word->content );
00334   }
00335   free(word);
00336   return 0;
00337 }
00338 
00339 fipa_word_t* fipa_word_Copy(fipa_word_t* src)
00340 {
00341   fipa_word_t* copy;
00342   if (src == NULL) return NULL;
00343   copy = fipa_word_New();
00344   copy->content = strdup(src->content);
00345   return copy;
00346 }
00347 
00348 
00349 fipa_string_t* fipa_string_New(void)
00350 {
00351   fipa_string_t* str;
00352   str = (fipa_string_t*)malloc(sizeof(fipa_string_t));
00353   memset(str, 0, sizeof(fipa_string_t));
00354   return str;
00355 }
00356 
00357 int fipa_string_Destroy(fipa_string_t* str)
00358 {
00359   if (str == NULL) return 0;
00360   if (str->content != NULL) {
00361     free(str->content);
00362   }
00363   free(str);
00364   return 0;
00365 }
00366 
00367 fipa_string_t* fipa_string_Copy(fipa_string_t* src)
00368 {
00369   fipa_string_t* copy;
00370   if (src == NULL) return NULL;
00371   copy = fipa_string_New();
00372   copy->content = strdup(src->content);
00373   return copy;
00374 }
00375 
00376 
00377 fipa_DateTime_t* fipa_DateTime_New(void)
00378 {
00379   fipa_DateTime_t* dt;
00380   dt = (fipa_DateTime_t*)malloc(sizeof(fipa_DateTime_t));
00381   memset(dt, 0, sizeof(fipa_DateTime_t));
00382   return dt;
00383 }
00384 
00385 int fipa_DateTime_Destroy(fipa_DateTime_t* dt)
00386 {
00387   if(dt == NULL) return 0;
00388   free(dt);
00389   return 0;
00390 }
00391 
00392 fipa_DateTime_t* fipa_DateTime_Copy(fipa_DateTime_t* src)
00393 {
00394   fipa_DateTime_t* copy;
00395   if (src == NULL) return NULL;
00396   copy = fipa_DateTime_New();
00397   *copy = *src;
00398   return copy;
00399 }
00400 
00401 
00402 fipa_url_t* fipa_url_New(void)
00403 {
00404   fipa_url_t* url;
00405   url = (fipa_url_t*)malloc(sizeof(fipa_url_t));
00406   memset(url, 0, sizeof(fipa_url_t));
00407   return url;
00408 }
00409 
00410 int fipa_url_Destroy(fipa_url_t* url)
00411 {
00412   if (url == NULL) return 0;
00413   if (url->str != NULL) {
00414     free(url->str);
00415   }
00416   free(url);
00417   return 0;
00418 }
00419 
00420 fipa_url_t* fipa_url_Copy(fipa_url_t* src)
00421 {
00422   fipa_url_t* copy;
00423   if (src == NULL) return NULL;
00424   copy = fipa_url_New();
00425   copy->str = strdup(src->str);
00426   return copy;
00427 }
00428 
00429 
00430 fipa_number_t* fipa_number_New(void)
00431 {
00432   fipa_number_t* num;
00433   num = (fipa_number_t*)malloc(sizeof(fipa_number_t));
00434   memset(num, 0, sizeof(fipa_number_t));
00435   return num;
00436 }
00437 
00438 int fipa_number_Destroy(fipa_number_t* number)
00439 {
00440   if (number == NULL) return 0;
00441   if (number->str != NULL){
00442     free(number->str);
00443   }
00444   free(number);
00445   return 0;
00446 }
00447 
00448 fipa_number_t* fipa_number_Copy(fipa_number_t* src)
00449 {
00450   fipa_number_t* copy;
00451   if (src == NULL) return NULL;
00452   copy = fipa_number_New();
00453   copy->str = strdup(src->str);
00454   return copy;
00455 }
00456 
00457 
00458 int fipa_acl_Parse(fipa_acl_message_p acl, fipa_message_string_p message)
00459 {
00460   int err = 0;
00461   if (fipa_GetAtom(message,'(')) {
00462     err = MC_ERR_PARSE;
00463     goto exit;
00464   }
00465   if (fipa_message_type_Parse(&(acl->performative), message)) {
00466     err = MC_ERR_PARSE;
00467     goto exit;
00468   }
00469   while(fipa_GetAtom(message, ')')){
00470     err = fipa_message_parameter_Parse(acl, message);
00471     if (err) return err;
00472   }
00473 
00474 exit:
00475   return err;
00476 }
00477 
00478 int fipa_message_parameter_Parse(fipa_acl_message_p acl, fipa_message_string_p message)
00479 {
00480   int err;
00481   fipa_word_t* word = NULL;
00482   char* parameter;
00483   if((err = fipa_GetAtom(message, ':'))) return err;
00484   if((err = fipa_word_Parse(&word, message))) return err;
00485   parameter = word->content;
00486   if (!strcmp(parameter, "sender")) {
00487     err = fipa_agent_identifier_Parse(&(acl->sender), message);
00488   } else if (!strcmp(parameter, "receiver")) {
00489     err = fipa_agent_identifier_set_Parse(&(acl->receiver), message);
00490   } else if (!strcmp(parameter, "content")) {
00491     err = fipa_string_Parse(&(acl->content), message);
00492   } else if (!strcmp(parameter, "reply-with")) {
00493     err = fipa_expression_Parse(&(acl->reply_with), message);
00494   } else if (!strcmp(parameter, "reply-by")) {
00495     err = fipa_datetime_Parse(&(acl->reply_by), message);
00496   } else if (!strcmp(parameter, "in-reply-to")) {
00497     err = fipa_expression_Parse(&(acl->in_reply_to), message);
00498   } else if (!strcmp(parameter, "reply-to")) {
00499     err = fipa_agent_identifier_set_Parse(&(acl->reply_to), message);
00500   } else if (!strcmp(parameter, "language")) {
00501     err = fipa_expression_Parse(&(acl->language), message);
00502   } else if (!strcmp(parameter, "encoding")) {
00503     err = fipa_expression_Parse(&(acl->encoding), message);
00504   } else if (!strcmp(parameter, "ontology")) {
00505     err = fipa_expression_Parse(&(acl->ontology), message);
00506   } else if (!strcmp(parameter, "protocol")) {
00507     err = fipa_word_Parse(&(acl->protocol), message);
00508   } else if (!strcmp(parameter, "conversation-id")) {
00509     err = fipa_expression_Parse(&(acl->conversation_id), message);
00510   } else {
00511     
00512     fprintf(stderr, "FIXME: No handling of user defined parameters. %s:%d\n",
00513         __FILE__, __LINE__);
00514     err = MC_ERR_PARSE;
00515   }
00516   fipa_word_Destroy(word);
00517   return err;
00518 }
00519 
00520 int fipa_message_type_Parse(
00521     enum fipa_performative_e* performative, 
00522     fipa_message_string_p message
00523     )
00524 {
00525   int err = 0;
00526   fipa_word_p word;
00527   err = fipa_word_Parse(&word, message);
00528   if (err) return err;
00529   if(!strcasecmp(word->content, "accept-proposal")) {
00530     *performative = FIPA_ACCEPT_PROPOSAL;
00531   } else if (!strcasecmp(word->content, "agree")) {
00532     *performative = FIPA_AGREE;
00533   } else if (!strcasecmp(word->content, "cancel")) {
00534     *performative = FIPA_CANCEL;
00535   } else if (!strcasecmp(word->content, "call-for-proposal")) {
00536     *performative = FIPA_CALL_FOR_PROPOSAL;
00537   } else if (!strcasecmp(word->content, "confirm")) {
00538     *performative = FIPA_CONFIRM;
00539   } else if (!strcasecmp(word->content, "disconfirm")) {
00540     *performative = FIPA_DISCONFIRM;
00541   } else if (!strcasecmp(word->content, "failure")) {
00542     *performative = FIPA_FAILURE;
00543   } else if (!strcasecmp(word->content, "inform")) {
00544     *performative = FIPA_INFORM;
00545   } else if (!strcasecmp(word->content, "inform-if")) {
00546     *performative = FIPA_INFORM_IF;
00547   } else if (!strcasecmp(word->content, "inform-ref")) {
00548     *performative = FIPA_INFORM_REF;
00549   } else if (!strcasecmp(word->content, "not-understood")) {
00550     *performative = FIPA_NOT_UNDERSTOOD;
00551   } else if (!strcasecmp(word->content, "propogate")) {
00552     *performative = FIPA_PROPOGATE;
00553   } else if (!strcasecmp(word->content, "propose")) {
00554     *performative = FIPA_PROPOSE;
00555   } else if (!strcasecmp(word->content, "proxy")) {
00556     *performative = FIPA_PROXY;
00557   } else if (!strcasecmp(word->content, "query-if")) {
00558     *performative = FIPA_QUERY_IF;
00559   } else if (!strcasecmp(word->content, "query-ref")) {
00560     *performative = FIPA_QUERY_REF;
00561   } else if (!strcasecmp(word->content, "refuse")) {
00562     *performative = FIPA_REFUSE;
00563   } else if (!strcasecmp(word->content, "reject-proposal")) {
00564     *performative = FIPA_REJECT_PROPOSAL;
00565   } else if (!strcasecmp(word->content, "request")) {
00566     *performative = FIPA_REQUEST;
00567   } else if (!strcasecmp(word->content, "request-when")) {
00568     *performative = FIPA_REQUEST_WHEN;
00569   } else if (!strcasecmp(word->content, "request-whenever")) {
00570     *performative = FIPA_REQUEST_WHENEVER;
00571   } else if (!strcasecmp(word->content, "subscribe")) {
00572     *performative = FIPA_SUBSCRIBE;
00573   } else {
00574     fprintf(stderr, "Unknown performative: '%s'. %s:%d\n",
00575         word->content, __FILE__, __LINE__);
00576     err = MC_ERR_PARSE;
00577   }
00578   fipa_word_Destroy(word);
00579   return err;
00580 }
00581 
00582 int fipa_GetAtom(
00583     fipa_message_string_p message,
00584     char expected_atom
00585     )
00586 {
00587   while
00588     (
00589      (*(message->parse) >= 0x00) &&
00590      (*(message->parse) <= 0x20)
00591     )
00592     {
00593       if (*(message->parse) == 0x00)
00594         return MC_ERR_PARSE;
00595       message->parse++;
00596     }
00597   if( *(message->parse) == expected_atom) {
00598     message->parse++;
00599     return MC_SUCCESS;
00600   } else {
00601     return MC_ERR_PARSE;
00602   }
00603 }
00604 
00605 int fipa_word_Parse(fipa_word_t** word, fipa_message_string_p message)
00606 {
00607   char* tmp;
00608   int i = 0;
00609   
00610   while
00611     (
00612      (*(message->parse)>=0x00) &&
00613      (*(message->parse)<=0x20)
00614     )
00615     {
00616       
00617       if (*(message->parse) == '\0') {
00618         return MC_ERR_PARSE;
00619       }
00620       message->parse++;
00621     }
00622   
00623   tmp = message->parse;
00624   while (*tmp > 0x20) {
00625     tmp++;
00626     i++;
00627   }
00628   *word = (fipa_word_t*)malloc(sizeof(fipa_word_t));
00629   CHECK_NULL(*word, exit(0););
00630   (*word)->content = malloc
00631     (
00632      sizeof(char) * (i+1)
00633     );
00634   CHECK_NULL((*word)->content, exit(0););
00635 
00636   
00637   i = 0;
00638   while( *(message->parse) > 0x20 ) {
00639     ((*word)->content)[i] = *(message->parse);
00640     message->parse++;
00641     i++;
00642   }
00643   ((*word)->content)[i] = '\0';
00644   return MC_SUCCESS;
00645 }
00646 
00647 int fipa_CheckNextToken(const fipa_message_string_p message, const char* token)
00648 {
00649   char* tmp = message->parse;
00650   while 
00651     (
00652      (*tmp >= 0x00) &&
00653      (*tmp <= 0x20)
00654     )
00655       tmp++;
00656   while (*token != '\0') {
00657     if (*token != *tmp) {
00658       return 0; 
00659     }
00660     token++;
00661     tmp++;
00662   }
00663   return 1; 
00664 }
00665 
00666 int fipa_expression_Parse(fipa_expression_t** expression, fipa_message_string_p message)
00667 {
00668   int i=0;
00669   *expression = (fipa_expression_t*)malloc(sizeof(fipa_expression_t));
00670   
00671 
00672 
00673   if (fipa_CheckNextToken(message, "(")) {
00674     (*expression)->type = FIPA_EXPR_EXPRESSION;
00675     if(fipa_GetAtom(message, '(')) {
00676       
00677       fprintf(stderr, "Fatal error. %s:%d\n", __FILE__, __LINE__);
00678       exit(0);
00679     }
00680     for 
00681       (
00682        i = 0; 
00683        !fipa_expression_Parse( &(((*expression)->content.expression)[i]), message);
00684        i++
00685       );
00686     if(fipa_GetAtom(message, ')')) {
00687       fprintf(stderr, "Parse error. %s:%d\n", __FILE__, __LINE__);
00688       return MC_ERR_PARSE;
00689     }
00690   } else if (
00691       
00692       !fipa_datetime_Parse(&((*expression)->content.datetime), message)
00693       ) 
00694   {
00695     (*expression)->type = FIPA_EXPR_DATETIME;
00696   } else if (
00697       
00698       !fipa_string_Parse(&((*expression)->content.string), message)
00699       )
00700   {
00701     (*expression)->type = FIPA_EXPR_STRING;
00702   } else if (
00703       
00704       !fipa_word_Parse(&((*expression)->content.word), message)
00705       )
00706   {
00707     (*expression)->type=FIPA_EXPR_WORD;
00708   }
00709   else
00710   {
00711     
00712     return MC_ERR_PARSE;
00713   }
00714   return MC_SUCCESS;
00715 }
00716 
00717 int fipa_GetNextWord(char** word, const fipa_message_string_p message)
00718 {
00719   char *tmp;
00720   int i = 0;
00721   int j;
00722   
00723   tmp = message->parse;
00724   while
00725     (
00726      (*tmp >= 0x00) &&
00727      (*tmp <= 0x20)
00728     )
00729       tmp++;
00730   
00731   
00732   if
00733     (
00734      ((*tmp >= 0x00) && (*tmp <= 0x20)) ||
00735      (*tmp == '(') ||
00736      (*tmp == ')') ||
00737      (*tmp == '#') ||
00738      ((*tmp >= 0x30) && (*tmp <= 0x39)) || 
00739      (*tmp == '-') ||
00740      (*tmp == '@')
00741     )
00742       return ERR;
00743   i++;
00744   tmp++;
00745   
00746   while
00747     (
00748      ((*tmp < 0x00) || (*tmp > 0x20)) &&
00749      (*tmp != '(') &&
00750      (*tmp != ')')
00751     ) {
00752       i++;
00753       tmp++;
00754     }
00755   
00756   *word = (char*)malloc(sizeof(char) * (i+1));
00757 
00758   for (j = 0; j < i; j++) {
00759     *((*word) + j) = *(message->parse+j);
00760   }
00761   *((*word)+j) = '\0';
00762   return MC_SUCCESS;
00763 }
00764 
00765 int fipa_GetWholeToken(char** word, fipa_message_string_p message)
00766 {
00767   char *tmp;
00768   int i = 0;
00769   int j;
00770   
00771   tmp = message->parse;
00772   while
00773     (
00774      (*tmp >= 0x00) &&
00775      (*tmp <= 0x20)
00776     )
00777     {
00778       tmp++;
00779       message->parse++;
00780     }
00781   
00782   i++;
00783   tmp++;
00784   
00785   while
00786     (
00787      ((*tmp < 0x00) || (*tmp > 0x20))
00788     ) {
00789       i++;
00790       tmp++;
00791     }
00792   
00793   *word = (char*)malloc(sizeof(char) * (i+1));
00794 
00795   for (j = 0; j < i; j++) {
00796     *((*word) + j) = *(message->parse+j);
00797   }
00798   *((*word)+j) = '\0';
00799   return MC_SUCCESS;
00800 }
00801 
00802 int fipa_datetime_Parse(fipa_DateTime_p* datetime, fipa_message_string_p message)
00803 {
00804   char *word;
00805   char *tmp;
00806   int i;
00807   char buf[5];
00808   
00809   fipa_GetWholeToken(&word, message);
00810   tmp = word;
00811   if (
00812       (*tmp == '+') ||
00813       (*tmp == '-')
00814      )
00815     tmp++;
00816   
00817   for(i = 0; i < 8; i++) {
00818     if (*tmp < 0x30 || *tmp > 0x39) {
00819       free(word);
00820       return MC_ERR_PARSE;
00821     }
00822     tmp++;
00823   }
00824   
00825   if (*tmp == 'T') {
00826     tmp++;
00827   } else {
00828     free(word);
00829     return MC_ERR_PARSE;
00830   }
00831   
00832   for(i = 0; i < 9; i++) {
00833     if(*tmp < 0x30 || *tmp > 0x39) {
00834       free(word);
00835       return MC_ERR_PARSE;
00836     }
00837     tmp++;
00838   }
00839 
00840   
00841   *datetime = (fipa_DateTime_p)malloc(sizeof(fipa_DateTime_t));
00842   tmp = word;
00843   switch(*tmp) {
00844     case '+':
00845       (*datetime)->sign = '+';
00846       tmp++;
00847       message->parse++;
00848       break;
00849     case '-':
00850       (*datetime)->sign = '-';
00851       tmp++;
00852       message->parse++;
00853       break;
00854     default:
00855       break;
00856   }
00857 
00858   
00859   for(i = 0; i < 4; i++) {
00860     buf[i] = *tmp;
00861     tmp++;
00862     message->parse++;
00863   }
00864   buf[i] = '\0';
00865   (*datetime)->year = atoi(buf);
00866 
00867   
00868   for(i = 0; i < 2; i++) {
00869     buf[i] = *tmp;
00870     tmp++;
00871     message->parse++;
00872   }
00873   buf[i] = '\0';
00874   (*datetime)->month = atoi(buf);
00875 
00876   
00877   for(i = 0; i < 2; i++) {
00878     buf[i] = *tmp;
00879     tmp++;
00880     message->parse++;
00881   }
00882   buf[i] = '\0';
00883   (*datetime)->month = atoi(buf);
00884 
00885   
00886   if (*tmp != 'T') {
00887     
00888     fprintf(stderr, "Fatal Error. %s:%d\n", __FILE__, __LINE__);
00889     exit(0);
00890   }
00891   tmp++;
00892   message->parse++;
00893 
00894   
00895   for(i = 0; i < 2; i++) {
00896     buf[i] = *tmp;
00897     tmp++;
00898     message->parse++;
00899   }
00900   buf[i] = '\0';
00901   (*datetime)->hour = atoi(buf);
00902 
00903   
00904   for(i = 0; i < 2; i++) {
00905     buf[i] = *tmp;
00906     tmp++;
00907     message->parse++;
00908   }
00909   buf[i] = '\0';
00910   (*datetime)->minute = atoi(buf);
00911 
00912   
00913   for(i = 0; i < 2; i++) {
00914     buf[i] = *tmp;
00915     tmp++;
00916     message->parse++;
00917   }
00918   buf[i] = '\0';
00919   (*datetime)->second = atoi(buf);
00920 
00921   
00922   for(i = 0; i < 3; i++) {
00923     buf[i] = *tmp;
00924     tmp++;
00925     message->parse++;
00926   }
00927   buf[i] = '\0';
00928   (*datetime)->millisecond = atoi(buf);
00929 
00930   if (*tmp == 'Z') {
00931     (*datetime)->is_utc = 1;
00932     message->parse++;
00933   }
00934   else
00935     (*datetime)->is_utc = 0;
00936   free(word);
00937   return MC_SUCCESS;
00938 }
00939 
00940 int fipa_string_Parse( fipa_string_p* fipa_string, fipa_message_string_p message)
00941 {
00942   int len;
00943   char *tmp;
00944   
00945   if(fipa_GetAtom(message, '\"')) {
00946     return MC_ERR_PARSE;
00947   }
00948 
00949   tmp = message->parse;
00950   len = 0;
00951   while 
00952     (
00953      (*tmp != '\0')
00954     )
00955     {
00956       if (*tmp == '\"') {
00957         break;
00958       }
00959       if (*tmp == '\\') {
00960         tmp++;
00961         len++;
00962       }
00963       tmp++;
00964       len++;
00965     }
00966   *fipa_string = (fipa_string_p)malloc(sizeof(fipa_string_t));
00967   (*fipa_string)->content = (char*)malloc
00968     (
00969      sizeof(char) * (len + 1)
00970     );
00971   len = 0;
00972   while (message->parse < tmp) {
00973     ((*fipa_string)->content)[len] = *(message->parse);
00974     len++;
00975     message->parse++;
00976   }
00977   ((*fipa_string)->content)[len] = '\0';
00978   
00979   if(fipa_GetAtom(message, '\"')) {
00980     return MC_ERR_PARSE;
00981   }
00982   return MC_SUCCESS;
00983 }
00984 
00985 int fipa_agent_identifier_Parse(fipa_agent_identifier_p* aid, fipa_message_string_p message)
00986 {
00987   int err = 0;
00988   fipa_word_t* word = NULL;
00989   char *rewind;
00990   if
00991     (
00992      (err = fipa_GetAtom(message, '(') ) 
00993     ) return err;
00994   if
00995     (
00996      (err = fipa_word_Parse(&word, message) )
00997     ) 
00998     {
00999       fipa_word_Destroy(word);
01000       return err;
01001     }
01002   if (strcmp(word->content, "agent-identifier")) {
01003     free(word->content);
01004     fipa_word_Destroy(word);
01005     return MC_ERR_PARSE;
01006   }
01007   fipa_word_Destroy(word);
01008   word = NULL;
01009   if 
01010     (
01011      (err = fipa_GetAtom(message, ':') )
01012     ) return err;
01013   if
01014     (
01015      (err = fipa_word_Parse(&word, message))
01016     ) 
01017     {
01018       fipa_word_Destroy(word);
01019       return err;
01020     }
01021   if (strcmp(word->content, "name")) {
01022     return MC_ERR_PARSE;
01023   }
01024   fipa_word_Destroy(word);
01025   word = NULL;
01026   
01027   *aid = (fipa_agent_identifier_p)malloc(sizeof(fipa_agent_identifier_t));
01028   memset(*aid, 0, sizeof(fipa_agent_identifier_t));
01029   if
01030     (
01031      (err = fipa_word_Parse(&word, message))
01032     )
01033     {
01034       fipa_word_Destroy(word);
01035       return err;
01036     }
01037   (*aid)->name = (char*)malloc
01038     (
01039      sizeof(char) * 
01040      (strlen(word->content)+1)
01041     );
01042   CHECK_NULL((*aid)->name, exit(0););
01043   strcpy((*aid)->name, word->content);
01044   
01045   fipa_word_Destroy(word);
01046 
01047   
01048 
01049   rewind = message->parse;
01050   if
01051     (
01052      (!(err = fipa_GetAtom(message, ':')))
01053     ) 
01054     {
01055       if
01056         (
01057          (err = fipa_word_Parse(&word, message))
01058         ) {
01059           message->parse = rewind;
01060           fipa_word_Destroy(word);
01061           return MC_ERR_PARSE;
01062         }
01063 
01064       if (!strcmp(word->content, "addresses"))
01065       {
01066         err = fipa_url_sequence_Parse(&((*aid)->addresses), message);
01067         if(err) {
01068           message->parse = rewind;
01069           fipa_word_Destroy(word);
01070           return err;
01071         }
01072       } else if (!strcmp(word->content, "resolvers"))
01073       {
01074         err = fipa_agent_identifier_set_Parse(&((*aid)->resolvers), message);
01075         if (err) {
01076           message->parse = rewind;
01077           fipa_word_Destroy(word);
01078           return err;
01079         }
01080       } else {
01081         message->parse = rewind;
01082       }
01083     }
01084   
01085   err = fipa_GetAtom(message, ')');
01086   fipa_word_Destroy(word);
01087   if (err) {return MC_ERR_PARSE;}
01088   return MC_SUCCESS;
01089   
01090 }
01091 
01092 int fipa_url_sequence_Parse(fipa_url_sequence_p* urls, fipa_message_string_p message)
01093 {
01094   int err;
01095   fipa_word_p word;
01096   int i;
01097   if
01098     (
01099      (err = fipa_GetAtom(message, '(') )
01100     ) return err;
01101   if
01102     (
01103      (err = fipa_word_Parse(&word, message) )
01104     ) return err;
01105   if ( strcmp(word->content, "sequence")) {
01106     fipa_word_Destroy(word);
01107     return MC_ERR_PARSE;
01108   }
01109   fipa_word_Destroy(word);
01110   *urls = fipa_url_sequence_New();
01111   
01112 
01113   (*urls)->urls = (fipa_url_t**)malloc(sizeof(fipa_url_t*)*20);
01114   i = 0;
01115   (*urls)->num = 0;
01116   while( fipa_GetAtom(message, ')') ) {
01117     fipa_url_Parse(&(*urls)->urls[i], message);
01118     i++;
01119     (*urls)->num++;
01120   }
01121   return 0;
01122 }
01123 
01124 int fipa_url_Parse(fipa_url_p* url, fipa_message_string_p message)
01125 {
01126   fipa_word_p word = NULL;
01127   int err;
01128   *url = (fipa_url_t*)malloc(sizeof(fipa_url_t));
01129   err = fipa_word_Parse(&word, message);
01130   if (err) {
01131     free(*url);
01132     if(word == NULL) fipa_word_Destroy(word);
01133     fprintf(stderr, "Error parsing. %s:%d\n", __FILE__, __LINE__);
01134     return err;
01135   }
01136   (*url)->str = strdup(word->content);
01137   fipa_word_Destroy(word);
01138   return 0;
01139 }
01140 
01141 
01142 
01143 
01144 int fipa_agent_identifier_set_Parse(fipa_agent_identifier_set_p* agent_ids, fipa_message_string_p message)
01145 {
01146   int err;
01147   fipa_word_p word;
01148   int i=0;
01149   
01150   if
01151     (
01152      (err = fipa_GetAtom(message, '(') )
01153     ) return err;
01154   if
01155     (
01156      (err = fipa_word_Parse(&word, message) )
01157     ) return err;
01158   if (!strcmp(word->content, "set")) {
01159     *agent_ids = (fipa_agent_identifier_set_p)malloc(sizeof(struct fipa_agent_identifier_set_s));
01160     (*agent_ids)->retain_order = 0;
01161   } else if (!strcmp(word->content, "sequence")) {
01162     *agent_ids = (fipa_agent_identifier_set_p)malloc(sizeof(struct fipa_agent_identifier_set_s));
01163     (*agent_ids)->retain_order = 1;
01164   } else {
01165     free(word->content);
01166     free(word);
01167     return MC_ERR_PARSE;
01168   }
01169   free(word->content);
01170   free(word);
01171   (*agent_ids)->fipa_agent_identifiers = 
01172     (fipa_agent_identifier_p*)malloc(20 * sizeof(fipa_agent_identifier_t*));
01173   while( fipa_GetAtom(message, ')') ) {
01174     err = fipa_agent_identifier_Parse
01175       (&(((*agent_ids)->fipa_agent_identifiers)[i]), message);
01176     if(err) return err;
01177     i++;
01178   }
01179   (*agent_ids)->num = i;
01180   return MC_SUCCESS;
01181 }
01182 
01183 
01184 
01185 int fipa_acl_Compose(dynstring_t** msg, fipa_acl_message_t* acl)
01186 {
01187   *msg = dynstring_New();
01188   dynstring_Append(*msg, "(");
01189   fipa_performative_Compose(*msg, acl->performative);
01190   if (acl->sender != NULL) {
01191     dynstring_Append(*msg, ":sender ");
01192     fipa_agent_identifier_Compose(*msg, acl->sender);
01193     dynstring_Append(*msg, "\n");
01194   }
01195   if (acl->receiver != NULL) {
01196     dynstring_Append(*msg, ":receiver ");
01197     fipa_agent_identifier_set_Compose(*msg, acl->receiver);
01198     dynstring_Append(*msg, "\n");
01199   }
01200   if (acl->reply_to) {
01201     dynstring_Append(*msg, ":reply-to ");
01202     fipa_agent_identifier_set_Compose(*msg, acl->reply_to);
01203     dynstring_Append(*msg, "\n");
01204   }
01205   if (acl->content) {
01206     dynstring_Append(*msg, ":content ");
01207     fipa_string_Compose(*msg, acl->content);
01208     dynstring_Append(*msg, "\n");
01209   }
01210   if (acl->language) {
01211     dynstring_Append(*msg, ":language ");
01212     fipa_expression_Compose(*msg, acl->language);
01213     dynstring_Append(*msg, "\n");
01214   }
01215   if (acl->encoding) {
01216     dynstring_Append(*msg, ":encoding ");
01217     fipa_expression_Compose(*msg, acl->encoding);
01218     dynstring_Append(*msg, "\n");
01219   }
01220   if (acl->ontology) {
01221     dynstring_Append(*msg, ":ontology ");
01222     fipa_expression_Compose(*msg, acl->ontology);
01223     dynstring_Append(*msg, "\n");
01224   }
01225   if (acl->protocol) {
01226     dynstring_Append(*msg, ":protocol ");
01227     fipa_word_Compose(*msg, acl->protocol);
01228     dynstring_Append(*msg, "\n");
01229   }
01230   if (acl->conversation_id) {
01231     dynstring_Append(*msg, ":conversation-id ");
01232     fipa_expression_Compose(*msg, acl->conversation_id);
01233     dynstring_Append(*msg, "\n");
01234   }
01235   if (acl->reply_with) {
01236     dynstring_Append(*msg, ":reply-with ");
01237     fipa_expression_Compose(*msg, acl->reply_with);
01238     dynstring_Append(*msg, "\n");
01239   }
01240   if (acl->in_reply_to) {
01241     dynstring_Append(*msg, ":in-reply-to ");
01242     fipa_expression_Compose(*msg, acl->in_reply_to);
01243     dynstring_Append(*msg, "\n");
01244   }
01245   if (acl->reply_by) {
01246     dynstring_Append(*msg, ":reply-by ");
01247     fipa_DateTime_Compose(*msg, acl->reply_by);
01248     dynstring_Append(*msg, "\n");
01249   }
01250   dynstring_Append(*msg, ")");
01251   return 0;
01252 }
01253 
01254 int fipa_performative_Compose(dynstring_t* msg, enum fipa_performative_e performative)
01255 {
01256   switch(performative) {
01257     case FIPA_ACCEPT_PROPOSAL:
01258       dynstring_Append(msg, "accept-proposal ");
01259       break;
01260     case FIPA_AGREE:
01261       dynstring_Append(msg, "agree ");
01262       break;
01263     case FIPA_CANCEL:
01264       dynstring_Append(msg, "cancel ");
01265       break;
01266     case FIPA_CALL_FOR_PROPOSAL:
01267       dynstring_Append(msg, "call-for-proposal ");
01268       break;
01269     case FIPA_CONFIRM:
01270       dynstring_Append(msg, "confirm ");
01271       break;
01272     case FIPA_DISCONFIRM:
01273       dynstring_Append(msg, "disconfirm ");
01274       break;
01275     case FIPA_FAILURE:
01276       dynstring_Append(msg, "failure ");
01277       break;
01278     case FIPA_INFORM:
01279       dynstring_Append(msg, "inform ");
01280       break;
01281     case FIPA_INFORM_IF:
01282       dynstring_Append(msg, "inform-if ");
01283       break;
01284     case FIPA_INFORM_REF:
01285       dynstring_Append(msg, "inform-ref ");
01286       break;
01287     case FIPA_NOT_UNDERSTOOD:
01288       dynstring_Append(msg, "not-understood ");
01289       break;
01290     case FIPA_PROPOGATE:
01291       dynstring_Append(msg, "propogate ");
01292       break;
01293     case FIPA_PROPOSE:
01294       dynstring_Append(msg, "propose ");
01295       break;
01296     case FIPA_PROXY:
01297       dynstring_Append(msg, "proxy ");
01298       break;
01299     case FIPA_QUERY_IF:
01300       dynstring_Append(msg, "query-if ");
01301       break;
01302     case FIPA_QUERY_REF:
01303       dynstring_Append(msg, "query-ref ");
01304       break;
01305     case FIPA_REFUSE:
01306       dynstring_Append(msg, "refuse ");
01307       break;
01308     case FIPA_REJECT_PROPOSAL:
01309       dynstring_Append(msg, "reject-proposal ");
01310       break;
01311     case FIPA_REQUEST:
01312       dynstring_Append(msg, "request ");
01313       break;
01314     case FIPA_REQUEST_WHEN:
01315       dynstring_Append(msg, "request-when ");
01316       break;
01317     case FIPA_REQUEST_WHENEVER:
01318       dynstring_Append(msg, "request-whenever ");
01319       break;
01320     case FIPA_SUBSCRIBE:
01321       dynstring_Append(msg, "subscribe ");
01322       break;
01323     default:
01324       return MC_ERR_PARSE;
01325   }
01326   return 0;
01327 }
01328 
01329 int fipa_url_sequence_Compose(dynstring_t* msg, fipa_url_sequence_t* urls)
01330 {
01331   int i;
01332   if(urls == NULL) return 0;
01333   if(urls->num == 0) return 0;
01334   dynstring_Append(msg, "(sequence ");
01335   for(i = 0; i < urls->num; i++) {
01336     fipa_url_Compose(msg, urls->urls[i]);
01337   }
01338   dynstring_Append(msg, ") ");
01339   return 0;
01340 }
01341 
01342 int fipa_agent_identifier_set_Compose(dynstring_t* msg, fipa_agent_identifier_set_t* ids)
01343 {
01344   int i;
01345   if(ids == NULL) return 0;
01346   if(ids->num == 0) return 0;
01347   dynstring_Append(msg, "(set ");
01348   for(i = 0; i < ids->num; i++) {
01349     fipa_agent_identifier_Compose(msg, ids->fipa_agent_identifiers[i]);
01350   }
01351   dynstring_Append(msg, ") ");
01352   return 0;
01353 }
01354 
01355 int fipa_agent_identifier_Compose(dynstring_t* msg, fipa_agent_identifier_t* id)
01356 {
01357   if(id == NULL) return 0;
01358   dynstring_Append(msg, "(agent-identifier ");
01359   dynstring_Append(msg, ":name ");
01360   dynstring_Append(msg, id->name);
01361   dynstring_Append(msg, " ");
01362 
01363   if (id->addresses != NULL) {
01364     if (id->addresses->num != 0) {
01365       dynstring_Append(msg, ":addresses ");
01366       fipa_url_sequence_Compose(msg, id->addresses);
01367     }
01368   }
01369 
01370   if (id->resolvers != NULL) {
01371     if (id->resolvers->num != 0) {
01372       dynstring_Append(msg, ":resolvers ");
01373       fipa_agent_identifier_set_Compose(msg, id->resolvers);
01374     }
01375   }
01376 
01377   dynstring_Append(msg, ") ");
01378   return 0;
01379 }
01380 
01381 int fipa_expression_Compose(dynstring_t* msg, fipa_expression_t* expr)
01382 {
01383   fipa_expression_t* tmp_expr;
01384   if (expr == NULL) return 0;
01385   switch(expr->type) {
01386     case FIPA_EXPR_WORD:
01387       fipa_word_Compose(msg, expr->content.word);
01388       break;
01389     case FIPA_EXPR_STRING:
01390       fipa_string_Compose(msg, expr->content.string);
01391       break;
01392     case FIPA_EXPR_NUMBER:
01393       fipa_number_Compose(msg, expr->content.number);
01394       break;
01395     case FIPA_EXPR_DATETIME:
01396       fipa_DateTime_Compose(msg, expr->content.datetime);
01397       break;
01398     case FIPA_EXPR_EXPRESSION:
01399       tmp_expr = expr->content.expression[0];
01400       while(tmp_expr != NULL) {
01401         fipa_expression_Compose(msg, tmp_expr);
01402         tmp_expr++;
01403       }
01404       break;
01405     default:
01406       return MC_ERR_PARSE;
01407   }
01408   return 0;
01409 }
01410 
01411 int fipa_word_Compose(dynstring_t* msg, fipa_word_t* word)
01412 {
01413   if (word == NULL) return 0;
01414   dynstring_Append(msg, word->content);
01415   dynstring_Append(msg, " ");
01416   return 0;
01417 }
01418 
01419 int fipa_string_Compose(dynstring_t* msg, fipa_string_t* string)
01420 {
01421   if (string == NULL) return 0;
01422   dynstring_Append(msg, "\"");
01423   dynstring_Append(msg, string->content);
01424   dynstring_Append(msg, "\" ");
01425   return 0;
01426 }
01427 
01428 int fipa_DateTime_Compose(dynstring_t* msg, fipa_DateTime_t* date)
01429 {
01430   char buf[40];
01431 
01432   if(date == NULL) return 0;
01433   dynstring_Append(msg, &date->sign);
01434   sprintf(buf, "%04d%02d%02dT%02d%02d%02d%03d", 
01435       date->year,
01436       date->month,
01437       date->day,
01438       date->hour,
01439       date->minute,
01440       date->second,
01441       date->millisecond
01442       );
01443   dynstring_Append(msg, buf);
01444   return 0;
01445 }
01446 
01447 
01448 int fipa_url_Compose(dynstring_t* msg, fipa_url_t* url)
01449 {
01450   if(url == NULL) return 0;
01451   dynstring_Append(msg, url->str);
01452   dynstring_Append(msg, " ");
01453   return 0;
01454 }
01455 
01456 int fipa_number_Compose(dynstring_t* msg, fipa_number_t* number)
01457 {
01458   if (number == NULL) return 0;
01459   dynstring_Append(msg, number->str);
01460   dynstring_Append(msg, " ");
01461   return 0;
01462 }
01463 
01464 struct fipa_acl_message_s* fipa_Reply(
01465     struct fipa_acl_message_s* acl)
01466 {
01467   
01468   struct fipa_acl_message_s* acl_reply;
01469 
01470   acl_reply = fipa_acl_message_New();
01471 
01472   
01473   
01474   if (acl->reply_to != NULL && acl->reply_to->num != 0) {
01475     acl_reply->receiver = fipa_agent_identifier_set_Copy(acl->reply_to);
01476   } else {
01477     acl_reply->receiver = fipa_agent_identifier_set_New();
01478     acl_reply->receiver->num = 1;
01479     acl_reply->receiver->retain_order = 0;
01480 
01481     acl_reply->receiver->fipa_agent_identifiers = (fipa_agent_identifier_t**)malloc(
01482         sizeof(fipa_agent_identifier_t*));
01483     acl_reply->receiver->fipa_agent_identifiers[0] = fipa_agent_identifier_Copy(
01484         acl->sender );
01485   }
01486   
01487   return acl_reply;
01488 }
01489 
01490 #undef FREEMEM