00001 %{
00009 #include <map>
00010 #include <vector>
00011 #include <typeinfo>
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #include <ctype.h>
00016 using namespace std;
00017
00018 #include "nodes/protomake.h"
00019
00021 int yylex(void);
00022
00027 extern int lines;
00028
00032 Program *root;
00033
00034 int yyerror(char *msg);
00035
00036 typedef struct FieldTypeInfo
00037 {
00038 FieldType::FType fType;
00039
00040 union {
00041 int numChars;
00042 char *cteStr;
00043 char *terminator;
00044 char *blanks;
00045 } info;
00046 } FieldTypeInfo;
00047
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 %}
00062
00064 %union {
00065 long number;
00066 char *string;
00067 SimpleImport *simpImp;
00068 Import *import;
00069 IdentifierList *idLst;
00070 Behavior *behavior;
00071 SimpleBehavior *simpBhv;
00072 Message *message;
00073 SimpleMessage *simpMsg;
00074 FieldType::FType fType;
00075 FieldTypeInfo fTypeInfo;
00076 FieldType *fieldType
00077 Expression *exp;
00078 FieldDeclaration *fieldDcl;
00079 SimpleFieldDeclaration *simpFld;
00080 StringLiteral *strLit;
00081 Process *proc;
00082 SimpleProcess *simpProc;
00083 Declaration *decl;
00084 SimpleDeclaration *simpDecl;
00085 Action *action;
00086 SimpleAction *simpAct;
00087 Type *type;
00088 Guard *guard;
00089 Statement *stmt;
00090 SimpleStatement *simpStmt;
00091 ArrayReference *arrayRef;
00092 LeftSideList *leftSideLst;
00093 LeftSide *leftSide;
00094 GuardedStatement *guardStmt;
00095 SimpleGuardedStatement *simpGuardStmt;
00096 FieldReference *fieldRef;
00097 ExpressionList *expLst;
00098 }
00099
00104 %token<string> tBEHAVIOR
00105 %token<string> tID
00106 %token<string> tSTRING
00107 %token<string> tTERMSTRING
00108 %token<number> tNUMBER
00109 %token<string> tMESSAGE
00110 %token<string> tIMPORT
00111 %token<string> tEXTERNAL
00112 %token<string> tBEGIN
00113 %token<string> tEND
00114 %token<string> tBITS
00115 %token<string> tBYTES
00116 %token<string> tSTRTYPE
00117 %token<string> tBLANKS
00118 %token<string> tPROCESS
00119 %token<string> tGLOBAL
00120 %token<string> tCONST
00121 %token<string> tVAR
00122 %token<string> tINTEGER
00123 %token<string> tADDRESS
00124 %token<string> tCLIENTADDRESS
00125 %token<string> tSERVERADDRESS
00126 %token<string> tARRAY
00127 %token<string> tOF
00128 %token<string> tRCV
00129 %token<string> tFROM
00130 %token<string> tTIMEOUT
00131 %token<string> tSKIP
00132 %token<string> tSEND
00133 %token<string> tTO
00134 %token<string> tIF
00135 %token<string> tFI
00136 %token<string> tDO
00137 %token<string> tOD
00138 %token<string> tACT
00139 %token<string> tIN
00140 %token<string> tPLUS
00141 %token<string> tMINUS
00142 %token<string> tTIMES
00143 %token<string> tDIVIDE
00144 %token<string> tBAND
00145 %token<string> tBOR
00146 %token<string> tNEG
00147 %token<string> tDIFFERENT
00148 %token<string> tLTE
00149 %token<string> tGTE
00150 %token<string> tEQUAL
00151 %token<string> tLT
00152 %token<string> tGT
00153 %token<number> tGUARD
00154 %token<number> tLBRACKET
00155 %token<number> tRBRACKET
00156 %token<number> tLPAR
00157 %token<number> tRPAR
00158 %token<number> tCOMMA
00159 %token<number> tCOLON
00160 %token<number> tSCOLON
00161 %token<number> tACTION
00162 %token<number> tDOT
00163 %token<number> tRANGE
00164 %token<number> tASSIGN
00165 %token<number> tDQUOTE
00166 %token<string> tSTART
00167 %token<string> tSTOP
00168
00170 %type<string> Program
00171 %type<import> Imports
00172 %type<import> ReallyImport
00173 %type<simpImp> Import
00174 %type<behavior> Behaviors
00175 %type<behavior> RealBehavior
00176 %type<simpBhv> Behavior
00177 %type<message> Messages
00178 %type<proc> Processes
00179 %type<simpProc> RealProcess
00180 %type<simpMsg> Message
00181 %type<number> External
00182 %type<fieldDcl> MessageBody
00183 %type<fieldDcl> Fields
00184 %type<simpFld> Field
00185 %type<fieldTyp> FieldType
00186 %type<exp> Init
00187 %type<fType> BitByte
00188 %type<fTypeInfo>StrType
00189 %type<simpDecl> DeclarationTypes
00190 %type<decl> Declarations
00191 %type<number> Global
00192 %type<idLst> IDs
00193 %type<type> Type
00194 %type<action> Actions
00195 %type<simpAct> Action
00196 %type<guard> GuardedAction
00197 %type<exp> Expression
00198 %type<fieldRef> FieldReference
00199 %type<arrayRef> ArrayReference
00200 %type<exp> ArrayPosition
00201 %type<stmt> Statements
00202 %type<simpStmt> Statement
00203 %type<leftSideLst> LeftSides
00204 %type<leftSide> LeftSide
00205 %type<expLst> Expressions
00206 %type<guardStmt> GuardedStatements
00207 %type<simpGuardStmt> GuardedStatement
00208
00210 %nonassoc tBOR, tBAND
00211 %nonassoc tNEG
00212 %nonassoc tLT, tLTE, tGT, tGTE, tEQUAL, tDIFFERENT
00213 %left tASSIGN
00214 %left tPLUS, tMINUS
00215 %left tTIMES, tDIVIDE
00216 %left UMINUS
00217
00218 %%
00219
00222 Program : Imports Behaviors Messages Processes
00223 {
00224 root = new Program(new SrcPosition(1), $1, $2, $3, $4);
00225 }
00226 ;
00227
00230 Imports : ReallyImport { $$ = $1; }
00231 | { $$ = NULL; }
00232 ;
00233
00235 ReallyImport : Import
00236 {
00238 $$ = $1;
00239 }
00240 | ReallyImport Import
00241 {
00242 $$ = new SequentialImport($2->getPosition(), $1, $2);
00243 }
00244 ;
00245
00247 Import : tIMPORT tSTRING
00248 {
00250 SrcPosition *srcPos = new SrcPosition(lines);
00251 StringLiteral *str = new StringLiteral(srcPos, $2);
00252 $$ = new SimpleImport(srcPos, str);
00253 }
00254 | error { yyerror("Import sintax error!"); }
00255 ;
00256
00259 Behaviors : RealBehavior { $$ = $1; }
00260 | { $$ = NULL}
00261 ;
00262
00264 RealBehavior : Behavior
00265 {
00266 $$ = $1;
00267 }
00268 | RealBehavior Behavior
00269 {
00270 $$ = new SequentialBehavior($2->getPosition(), $1, $2);
00271 }
00272 ;
00273
00275 Behavior : tBEHAVIOR IDs
00276 {
00277 $$ = new SimpleBehavior($2->getPosition(), $2);
00278 }
00279 ;
00280
00283 Messages : Message { $$ = $1; }
00284 | Messages Message { $$ = new SequentialMessage($2->getPosition(), $1, $2); }
00285 ;
00286
00289 Message : External tMESSAGE tID tLPAR tID tCOMMA tID tRPAR MessageBody
00290 {
00291 $$ = new SimpleMessage($9->getPosition(), new Identifier($9->getPosition(), $3),
00292 $9, new Identifier($9->getPosition(), $5),
00293 new Identifier($9->getPosition(), $7), $1);
00294 }
00295 | External tMESSAGE tID MessageBody
00296 {
00297 $$ = new SimpleMessage($4->getPosition(), new Identifier($4->getPosition(), $3),
00298 $4, NULL, NULL, $1);
00299 }
00300 ;
00301
00304 External : tEXTERNAL { $$ = 1; }
00305 | { $$ = 0 }
00306 ;
00307
00310 MessageBody : tBEGIN Fields tEND { $$ = $2; }
00311 | error { yyerror("Message body sintax error!"); }
00312 ;
00313
00316 Fields : Field { $$ = $1; }
00317 | Fields tCOMMA Field { $$ = new SequentialFieldDeclaration($3->getPosition(), $1, $3); }
00318 ;
00319
00322 Field : tID tCOLON FieldType Init
00323 {
00324 Identifier *id = new Identifier($1->getPosition(), $1);
00325 $$ = new SimpleFieldDeclaration($1->getPosition(), id, $2, $3, $4);
00326 }
00327
00328 | tID tGUARD tCOLON tSTRTYPE tLPAR tTERMSTRING tRPAR tSTOP tLPAR tTERMSTRING tRPAR
00329 {
00330
00331 $$ = NULL
00332 }
00333 | error { yyerror("Field declaration sintax error!"); }
00334 ;
00335
00338 Init : tEQUAL Expression { $$ = $2; }
00339 | { $$ = NULL; }
00340 ;
00341
00344 FieldType : Expression BitByte
00345 {
00346 $$ = new FieldType($1->getPosition(), $1, $2);
00347 }
00348
00349 | StrType
00350 {
00351
00352 $$ = NULL;
00353 }
00354
00355 | error { yyerror("Field type sintaxe error!"); }
00356 ;
00357
00360 BitByte : tBITS { $$ = FieldType::BIT; }
00361 | tBYTES { $$ = FieldType::BYTE; }
00362 | error { yyerror("Undefined field type!"); }
00363 ;
00364
00365 StrType : tSTRTYPE tLPAR tNUMBER tRPAR
00366 {
00367 $$.fType = FieldType::STRN;
00368 $$.info.number = $3;
00369 }
00370
00371 | tSTRTYPE tLPAR tSTRING tRPAR
00372 {
00373 $$.fType = FieldType::STRCTE;
00374 $$.info.cteStr = $3;
00375 }
00376 | tSTRTYPE tLPAR tTERMSTRING tRPAR
00377 {
00378 $$.fType = FieldType::STRTERM;
00379 $$.info.terminator = $3;
00380 }
00381 | tBLANKS tLPAR tTERMSTRING tRPAR
00382 {
00383 $$.fType = FieldType::BLANKS;
00384 $$.info.blanks = $3;
00385 }
00386
00387 | error { yyerror("Undefined field type!"); }
00388 ;
00389
00392 Processes : RealProcess
00393 {
00394 $$ = $1;
00395 }
00396 | Processes RealProcess
00397 {
00398 $$ = new SequentialProcess($2->getPosition(), $1, $2);
00399 }
00400 ;
00401
00403 RealProcess : tPROCESS tID Declarations tBEGIN Actions tEND
00404 {
00405
00406 $$ = new SimpleProcess($4->getPosition(),
00407 new Identifier($4->getPosition(), $3), $4, $6, 0);
00408 }
00409 | error { yyerror("Process defenition sintax error!"); }
00410 ;
00411
00414 DeclarationTypes : tCONST IDs tCOLON Type Init
00415 {
00416 $$ = new SimpleDeclaration(new SrcPosition(lines), $2, $4, $5, true);
00417 }
00418 | Global tVAR IDs tCOLON Type Init
00419 {
00420 $$ = new SimpleDeclaration(new SrcPosition(lines), $3, $5, $6, false, $1);
00421 }
00422
00423 | { $$ = NULL; }
00424 | error { yyerror("DeclarationType syntax error!"); }
00425 ;
00426
00427 Global : tGLOBAL { $$ = 1;}
00428 | { $$ = 0;}
00429 ;
00430
00433 Declarations : DeclarationTypes
00434 {
00435 $$ = $1;
00436 }
00437 | Declarations tSCOLON DeclarationTypes
00438 {
00439 $$ = new SequentialDeclaration($3->getPosition(), $1, $3);
00440 }
00441 ;
00442
00443
00446 IDs : tID
00447 {
00448 Identifier *identifier = new Identifier(new SrcPosition(lines), $1);
00449 $$ = new SimpleIdentifierList(identifier->getPosition(), identifier);
00450 }
00451
00452 | IDs tCOMMA tID
00453 {
00454 Identifier *identifier = new Identifier(new SrcPosition(lines), $3);
00455 SimpleIdentifierList *simpIdList = new SimpleIdentifierList(identifier->getPosition(), identifier);
00456 $$ = new SequentialIdentifierList(identifier->getPosition(), $1, simpIdList);
00457 }
00458
00459 | error { yyerror("Identifier list sintax error!"); }
00460 ;
00461
00464 Type : tINTEGER {$$ = new Type(new SrcPosition(lines), Type::INTEGER);}
00465 | tNUMBER tRANGE tNUMBER { $$ = new RangeType(new SrcPosition(lines), Type::RANGE, $1, $3); }
00466 | tADDRESS { $$ = new Type(new SrcPosition(lines), Type::ADDRESS); }
00467 | tCLIENTADDRESS { $$ = new Type(new SrcPostion(lines), Type::CLIENTADDRESS); }
00468 | tSERVERADDRESS { $$ = new Type(new SrcPostion(lines), Type::SERVERADDRESS); }
00469 | tARRAY tLBRACKET tNUMBER tRBRACKET tOF Type {$$ = new ArrayType(new SrcPosition(lines), Type::ARRAY, $6, $3);}
00470 | error {yyerror("Undefined type!");}
00471 ;
00472
00475 Actions : Action {$$ = $1;}
00476 | Actions tGUARD Action {$$ = new SequentialAction($3->getPosition(), $1, $3);}
00477 ;
00478
00484 Action : GuardedAction tACTION Statements {$$ = new SimpleAction($1->getPosition(), $1, $3);}
00485 | error {yyerror("Action syntax error!");}
00486 ;
00487
00490 GuardedAction : Expression { $$ = new GuardExpression($1->getPosition(), $1); }
00491 | tRCV tID tFROM tID
00492 {
00493
00494 SrcPosition *pos = new SrcPosition(lines);
00495
00496 ReceiveStatement *rs = new ReceiveStatement(pos, new Identifier(pos, $2),
00497 new Identifier(pos, $4), NULL);
00498 $$ = new GuardReceive(pos, rs);
00499 }
00500 | tTIMEOUT tID
00501 {
00502 SrcPosition *pos = new SrcPosition(lines);
00503
00504 $$ = new GuardTimeout(pos, new Identifier(pos, $2));
00505 }
00506 | error { yyerror("Invalid guard!"); }
00507 ;
00508
00511 Expression : tLPAR Expression tRPAR { $$ = $2; }
00512
00513 | Expression tEQUAL Expression
00514 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00515
00516 | Expression tGT Expression
00517 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00518
00519 | Expression tLT Expression
00520 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00521
00522 | Expression tGTE Expression
00523 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00524
00525 | Expression tLTE Expression
00526 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00527
00528 | Expression tDIFFERENT Expression
00529 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00530
00531 | Expression tBOR Expression
00532 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00533
00534 | Expression tBAND Expression
00535 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00536
00537 | Expression tPLUS Expression
00538 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00539
00540 | Expression tMINUS Expression
00541 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00542
00543 | Expression tTIMES Expression
00544 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00545
00546 | Expression tDIVIDE Expression
00547 { $$ = new BinaryExpression(new SrcPosition(lines), $1, $3, $2); }
00548
00549 | tNEG Expression { $$ = new UnaryExpression(new SrcPosition(lines), $2, $1); }
00550
00551 | tMINUS Expression %prec UMINUS { $$ = new UnaryExpression(new SrcPosition(lines), $2, $1); }
00552
00553 | FieldReference { $$ = $1; }
00554 | ArrayReference { $$ = $1; }
00555 | tID { $$ = new Identifier(new SrcPosition(lines), $1); }
00556 | tNUMBER { $$ = new IntegerLiteral(new SrcPosition(lines), $1); }
00557 | tSTRING { $$ = new StringLiteral(new SrcPosition(lines), $1); }
00558 ;
00559
00562 FieldReference : tID tDOT tID
00563 {
00564 SrcPosition *pos = new SrcPosition(lines);
00565 $$ = new FieldReference(pos, new Identifier(pos, $1), new Identifier(pos, $3));
00566 }
00567 ;
00568
00571 ArrayReference : tID ArrayPosition { $$ = new SimpleArrayReference($2->getPosition(), new Identifier($2->getPosition(), $1), $2); }
00572 | ArrayReference ArrayPosition {$$ = new MultipleArrayReference($1->getPosition(), $1, $2);}
00573 ;
00574
00577 ArrayPosition : tLBRACKET Expression tRBRACKET { $$ = $2; }
00578 ;
00579
00582 Statements : Statement {$$ = $1;}
00583 | Statements tSCOLON Statement {$$ = new SequentialStatement($3->getPosition(), $1, $3);}
00584 ;
00585
00588 Statement : tSKIP {$$ = new SkipStatement(new SrcPosition(lines));}
00589 | LeftSides tASSIGN Expressions {$$ = new AssignStatement($1->getPosition(), $1, $3);}
00590 | tRCV tID tFROM tID
00591 {
00592
00593 SrcPosition *pos = new SrcPosition(lines);
00594 $$ = new ReceiveStatement(pos, new Identifier(pos, $2), new Identifier(pos, $4), NULL);
00595 }
00596 | tSEND tID tTO tID
00597 {
00598
00599 SrcPosition *pos = new SrcPosition(lines);
00600 $$ = new SendStatement(pos, new Identifier(pos, $2), new Identifier(pos, $4), NULL);
00601 }
00602 | tIF GuardedStatements tFI { $$ = new IfStatement($2->getPosition(), $2); }
00603 | tDO GuardedStatement tOD { $$ = new DoStatement($2->getPosition(), $2); }
00604 | tACT tID tIN Expression { $$ = new ActStatement($4->getPosition(), new Identifier($4->getPosition(), $2) ,$4); }
00605 | tSTART tID
00606 {
00607 SrcPosition *pos = new SrcPosition(lines);
00608 $$ = new StartStatement(pos, new Identifier(pos, $2));
00609 }
00610 | tSTOP { $$ = new StopStatement(new SrcPosition(lines)); }
00611
00612 | tID tDOT tID tLPAR Expressions tRPAR
00613 {
00614 $$ = new BehaviorStatement($5->getPosition(),
00615 new Identifier($5->getPosition(), $1),
00616 new Identifier($5->getPosition(), $3),
00617 $5);
00618 }
00619 ;
00620
00623 LeftSides : LeftSide { $$ = new SimpleLeftSideList($1->getPosition(), $1); }
00624 | LeftSides tCOMMA LeftSide
00625 {
00626 $$ = new SequentialLeftSideList($3->getPosition(), $1,
00627 new SimpleLeftSideList($3->getPosition(), $3));
00628 }
00629 ;
00630
00633 LeftSide : tID { $$ = new Identifier(new SrcPosition(lines), $1); }
00634 | FieldReference { $$ = $1; }
00635 | ArrayReference { $$ = $1; }
00636 ;
00637
00640 Expressions : Expression { $$ = new SimpleExpressionList($1->getPosition(), $1); }
00641 | Expressions tCOMMA Expression
00642 {
00643 $$ = new SequentialExpressionList($1->getPosition(), $1,
00644 new SimpleExpressionList($1->getPosition(), $3));
00645 }
00646 ;
00647
00650 GuardedStatements : GuardedStatement { $$ = $1; }
00651 | GuardedStatements tGUARD GuardedStatement
00652 {
00653 $$ = new SequentialGuardedStatement($1->getPosition(), $1, $3);
00654 }
00655 ;
00656
00659 GuardedStatement : Expression tACTION Statements
00660 {
00661 $$ = new SimpleGuardedStatement($1->getPosition(), $1, $3);
00662 }
00663 ;
00664
00665 %%
00666
00667 int main(int argc, char **argv)
00668 {
00669 extern FILE *yyin;
00670
00671 if (argc != 2)
00672 {
00673 fprintf(stderr, "Uso: protomake <arquivo-entrada>\n");
00674 exit(1);
00675 }
00676
00677 if ((yyin = fopen(argv[1], "r")) == NULL)
00678 {
00679 fprintf(stderr, "Erro ao tentar abrir o arquivo %s!\n", argv[1]);
00680 exit(1);
00681 }
00682
00683 if (yyparse())
00684 {
00685 fprintf(stderr, "Não foi possível compilar %s!\n", argv[1]);
00686 exit(1);
00687 }
00688
00689 TypeCheckerVisitor typeChecker;
00690 root->visit(typeChecker);
00691
00692 CCodeGeneratorVisitor ccodeGenerator;
00693 root->visit(ccodeGenerator);
00694
00695 JavaCodeGeneratorVisitor java("./code/teste.java");
00696 root->visit(java);
00697
00698 fprintf(stderr, "Sintaxe de %s correta!\n", argv[1]);
00699 fclose(yyin);
00700
00701 if (etherInfo != NULL)
00702 {
00703 fprintf(stderr, "Gerando o plugin do ethereal para o protocolo...\n");
00704 generateEtherealPlugin(&fiMap, etherInfo);
00705 fprintf(stderr, "Plugin gerado!\n");
00706 }
00707
00708 return 0;
00709 }
00710
00711 int yyerror(char *msg)
00712 {
00713 fprintf(stderr, "Line %d: %s\n", lines+1, msg);
00714 exit(1);
00715
00716 return 0;
00717 }
00718
00720 static void generateEtherealPlugin(map<string, vector<FieldInfo> > *fiMap,
00721 multimap<EtherType, EtherInfoType> *eit)
00722 {
00723 multimap<EtherType, EtherInfoType>::iterator itr;
00724
00726 if (eit->count(NAME) > 1)
00727 {
00728 itr = eit->find(NAME);
00729 itr++;
00730 fprintf(stderr, "Line %d: More than one name was defined for the protocol!\n",
00731 (*itr).second.lines + 1);
00732 exit(1);
00733 }
00734 else if (eit->count(NAME) == 0)
00735 {
00736 fprintf(stderr, "No name was defined for the protocol!\n");
00737 exit(1);
00738 }
00739 if (eit->count(ABBREV) > 1)
00740 {
00741 itr = eit->find(ABBREV);
00742 itr++;
00743 fprintf(stderr, "Line %d: More than one short name was defined for the protocol!\n",
00744 (*itr).second.lines + 1);
00745 exit(1);
00746 }
00747 else if (eit->count(ABBREV) == 0)
00748 {
00749 fprintf(stderr, "No short name was defined for the protocol!\n");
00750 exit(1);
00751 }
00752 else if (eit->count(PORT) > 1)
00753 {
00754 itr = eit->find(PORT);
00755 itr++;
00756 fprintf(stderr, "Line %d: More than one port was defined for the protocol!\n",
00757 (*itr).second.lines + 1);
00758 exit(1);
00759 }
00760 else if (eit->count(PORT) == 0)
00761 {
00762 fprintf(stderr, "No port was defined for the protocol!\n");
00763 exit(1);
00764 }
00765 else if (eit->count(TRANSPORT) > 1)
00766 {
00767 itr = eit->find(TRANSPORT);
00768 itr++;
00769 fprintf(stderr, "Line %d: More than one transport protocol was defined for the protocol!\n",
00770 (*itr).second.lines + 1);
00771 exit(1);
00772 }
00773 else if (eit->count(TRANSPORT) == 0)
00774 {
00775 fprintf(stderr, "No transport protocol was defined for the protocol!\n");
00776 exit(1);
00777 }
00778
00780 itr = eit->find(ABBREV);
00781 FILE *plugin;
00782 char fileName[256];
00783 char *abbrev = ++((*itr).second.string);
00784 unsigned i;
00785
00789 abbrev[strlen(abbrev)-1] = '\0';
00790 for (i = 0; abbrev[i]; i++)
00791 abbrev[i] = tolower(abbrev[i]);
00792
00793
00794 sprintf(fileName, "./plugin/packet-%s.c", (*itr).second.string);
00795 if ((plugin = fopen(fileName, "w")) == NULL)
00796 {
00797 fprintf(stderr, "Unable to create %s!\n", fileName);
00798 exit(1);
00799 }
00800
00802 writeHeader(plugin, fileName, eit);
00803
00805
00806 int j;
00807 FieldInfo fi;
00808 fi.identifier = "code";
00809 fi.bitByte = FieldType::BIT;
00810 fi.size = NULL;
00811
00812 j = 1;
00813 fprintf(plugin, "/** Message structures. Inicialize the protocol and registered fields */\n");
00814 for (map<string, vector<FieldInfo> >::iterator itr = fiMap->begin();
00815 itr != fiMap->end();
00816 itr++, j++)
00817 {
00818 fi.init = new IntegerLiteral(NULL, j);
00819 ((*itr).second).push_back(fi);
00820
00821 fprintf(plugin, "typedef struct {\n");
00822 for (i = 0; i < (*itr).second.size(); i++)
00823 fprintf(plugin, "\tint %s_%s;\n", abbrev, ((*itr).second)[i].identifier);
00824 fprintf(plugin, "} hf_%s_fields;\n", (*itr).first.c_str());
00825 fprintf(plugin, "static hf_%s_fields hf_%s = { ", (*itr).first.c_str(), (*itr).first.c_str());
00826 for (i = 0; i < (*itr).second.size(); i++)
00827 {
00828 if (!i) fprintf(plugin, "-1");
00829 else fprintf(plugin, ", -1");
00830 }
00831 fprintf(plugin, " };\n\n");
00832 }
00833 fprintf(plugin, "static int proto_%s = -1;\n\n", abbrev);
00834 fprintf(plugin, "/* Initialize the subtree pointers */\n");
00835 fprintf(plugin, "static gint ett_%s = -1;\n\n", abbrev);
00836
00838 writeDissector(plugin, fiMap, eit);
00839
00841 fprintf(plugin, "void proto_register_%s(void)\n{\n", abbrev);
00842 fprintf(plugin, "/** Setup list of header fields */\n");
00843 fprintf(plugin, "\t static hf_register_info hf[] = {\n");
00844
00846 for (map<string, vector<FieldInfo> >::iterator itr = fiMap->begin();
00847 itr != fiMap->end();
00848 itr++)
00849 {
00850 if (itr != fiMap->begin())
00851 fprintf(plugin, ",\n");
00852
00853 for (i = 0; i < (*itr).second.size(); i++)
00854 {
00855 if (i)
00856 fprintf(plugin, ",\n");
00857 fprintf(plugin, "\t\t{ &(hf_%s.%s_%s),\n", (*itr).first.c_str(), abbrev,
00858 ((*itr).second)[i].identifier);
00859 fprintf(plugin, "\t\t\t{ \"%s\", \"%s.%s_%s\",\n", ((*itr).second)[i].identifier,
00860 abbrev,
00861 (*itr).first.c_str(),
00862 ((*itr).second)[i].identifier);
00863
00864 if ((*itr).second[i].bitByte == FieldType::BIT)
00865 fprintf(plugin, "\t\t\tFT_INT32, BASE_DEC, NULL, 0x0,\n\t\t\t\"%s\" }\n", ((*itr).second)[i].identifier);
00866 else
00867 fprintf(plugin, "\t\t\tFT_STRING, BASE_NONE, NULL, 0x0,\n\t\t\t\"%s\" }\n", ((*itr).second)[i].identifier);
00868 fprintf(plugin, "\t\t}");
00869 }
00870 }
00871 fprintf(plugin, "\n\t};\n\n");
00872
00873 fprintf(plugin, "/** Setup protocol subtree array */\n");
00874 fprintf(plugin, "\tstatic gint *ett[] = { &ett_%s };\n\n", abbrev);
00875
00876 fprintf(plugin, "/** Register the protocol name and description */\n");
00877 char *ABBREV = strdup(abbrev);
00878 for (i = 0; ABBREV[i]; i++)
00879 ABBREV[i] = toupper(ABBREV[i]);
00880
00881 char *name = (*(eit->find(NAME))).second.string;
00882 fprintf(plugin, "\tproto_%s = proto_register_protocol(\"%s\",\n"
00883 "\t \"%s\",\n"
00884 "\t \"%s\");\n\n",
00885 abbrev, name, ABBREV, abbrev);
00886
00887 fprintf(plugin, "/** Required function calls to register the header fields and subtrees used */\n");
00888 fprintf(plugin, "\tproto_register_field_array(proto_%s, hf, array_length(hf));\n", abbrev);
00889 fprintf(plugin, "\tproto_register_subtree_array(ett, array_length(ett));\n}");
00890
00892 writeRest(plugin, (*(eit->find(TRANSPORT))).second.string, (*(eit->find(PORT))).second.string, abbrev);
00893 fclose(plugin);
00894
00895 FILE *makefile = fopen("./plugin/Makefile.am", "w");
00896 if (makefile)
00897 {
00898 fprintf(makefile, "INCLUDES = -I$(top_src_dir)\n\n");
00899
00900 fprintf(makefile, "plugindir = @plugindir@\n\n");
00901
00902 fprintf(makefile, "plugin_LTLIBRARIES = %s.la\n", abbrev);
00903 fprintf(makefile, "%s_la_SOURCES = packet-%s.c\n", abbrev, abbrev);
00904 fprintf(makefile, "%s_la_LDFLAGS = -module -avoid-version\n\n", abbrev);
00905
00906 fprintf(makefile, "LIB = \n\n");
00907
00908 fprintf(makefile, "%s_la_DEPENDENCIES = packet-%s-static.o\n\n", abbrev, abbrev);
00909
00910 fprintf(makefile, "packet-%s-static.o: packet-%s.c\n", abbrev, abbrev);
00911 fprintf(makefile, "\t$(LTCOMPILE) -c -o packet-%s-static.o -D__ETHEREAL_STATIC__ $(srcdir)/packet-%s.c\n",
00912 abbrev, abbrev);
00913
00914 fprintf(makefile, "CLEANFILES = %s \n", abbrev);
00915 fprintf(makefile, "EXTRA_DIST = Makefile.nmake\n");
00916 }
00917 else fprintf(stderr, "Unable to create Makfile.am!\n");
00918 fclose(makefile);
00919
00920 makefile = fopen("./plugin/Makefile.nmake", "w");
00921 if (makefile)
00922 {
00923 fprintf(makefile, "include ..\\..\\config.nmake\n\n");
00924
00925 fprintf(makefile, "CFLAGS=/DHAVE_CONFIG_H /I../.. /I../../wiretap \\\n");
00926 fprintf(makefile, "\t/I$(GLIB_DIR) /I$(GTK_DIR) /I$(GLIB_DIR)/gmodule \\\n");
00927 fprintf(makefile, "/I$(PCAP_DIR)\\include $(LOCAL_CFLAGS)\n\n");
00928
00929 fprintf(makefile, "OBJECTS=packet-%s.obj\n\n", abbrev);
00930 fprintf(makefile, "%s.dll %s.exp %s.lib : packet-%s.obj ..\\plugin_api.obj\n",
00931 abbrev, abbrev, abbrev, abbrev);
00932 fprintf(makefile, "\tlink -dll /out:%s.dll packet-%s.obj ..\\plugin_api.obj \\\n",
00933 abbrev, abbrev);
00934 fprintf(makefile, "$(GLIB_DIR)\\glib-$(GLIB_VERSION).lib\n\n");
00935 fprintf(makefile, "clean:\n\trm -f $(OBJECTS) %s.dll %s.exp %s.lib\n",
00936 abbrev, abbrev, abbrev);
00937 }
00938 else fprintf(stderr, "Unable to create Makefile.nmake!\n");
00939 fclose(makefile);
00940 }
00941
00942 static void writeHeader(FILE *plugin, char *fileName,
00943 multimap<EtherType, EtherInfoType> *eit)
00944 {
00945 int total;
00946 char *author, *email;
00947 char *name = ++((*(eit->find(NAME))).second.string);
00948 multimap<EtherType, EtherInfoType>::iterator itr;
00949
00950 name[strlen(name)-1] = '\0';
00951 fprintf(plugin, "/* %s\n", &fileName[2]);
00952 fprintf(plugin, " * Routines for %s dissection\n", name);
00953
00954 fprintf(plugin, " * Copyright 2003");
00955 for (total = eit->count(AUTHOR), itr = eit->find(AUTHOR);
00956 total > 0;
00957 itr++, total--)
00958 {
00959 author = ++((*itr).second.string);
00960
00961 author[strlen(author) - 1] = '\0';
00962 fprintf(plugin, ", %s", author);
00963 }
00964
00965 fprintf(plugin, " <");
00966 for (total = eit->count(EMAIL), itr = eit->find(EMAIL);
00967 total > 0;
00968 itr++, total--)
00969 {
00970 email = ++((*itr).second.string);
00971
00972 email[strlen(email) - 1] = '\0';
00973 fprintf(plugin, "%s, ", email);
00974 }
00975 fprintf(plugin, ">\n");
00976
00977 char *header = " * \n\
00978 * Ethereal - Network traffic analyzer\n\
00979 * By Gerald Combs <gerald@ethereal.com>\n\
00980 * Copyright 1998 Gerald Combs\n\
00981 * \n\
00982 * Generated from ProtoMake by Igor Cananéa, Fábio Guerra, Rodrigo Araújo &\n\
00983 * Thiago Souto Maior, Copyright 2003.\n\
00984 *\n\
00985 * This program is free software; you can redistribute it and/or\n\
00986 * modify it under the terms of the GNU General Public License\n\
00987 * as published by the Free Software Foundation; either version 2\n\
00988 * of the License, or (at your option) any later version.\n\
00989 *\n\
00990 * This program is distributed in the hope that it will be useful,\n\
00991 * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
00992 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
00993 * GNU General Public License for more details.\n\
00994 *\n\
00995 * You should have received a copy of the GNU General Public License\n\
00996 * along with this program; if not, write to the Free Software\n\
00997 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\
00998 */\n\
00999 \n\
01000 #ifdef HAVE_CONFIG_H\n\
01001 # include \"config.h\"\n\
01002 #endif\n\
01003 \n\
01004 #include <stdio.h>\n\
01005 #include <stdlib.h>\n\
01006 #include <string.h>\n\
01007 \n\
01008 /* Includes glib.h! */\n\
01009 #include <gmodule.h>\n\
01010 \n\
01011 #ifdef NEED_SNPRINTF_H\n\
01012 # include \"snprintf.h\"\n\
01013 #endif\n\
01014 \n\
01015 #include <epan/packet.h>\n\
01016 #include \"plugins/plugin_api.h\"\n\
01017 #include \"plugins/plugin_api_defs.h\"\n\
01018 \n\
01019 #ifndef __ETHEREAL_STATIC__\n\
01020 G_MODULE_EXPORT const gchar version[] = \"1.0\";\n\
01021 #endif\n\n";
01022
01023 fprintf(plugin, "%s", header);
01024 }
01025
01026
01027 static void writeDissector(FILE *plugin, map<string, vector<FieldInfo> > *fiMap,
01028 multimap<EtherType, EtherInfoType> *eit)
01029 {
01030 char *abbrev = (*(eit->find(ABBREV))).second.string;
01031 char *ABBREV = strdup(abbrev);
01032 unsigned i;
01033
01034 for (i = 0; ABBREV[i]; i++)
01035 ABBREV[i] = toupper(ABBREV[i]);
01036
01037 fprintf(plugin, "/** Dissector main code! */\n");
01038 fprintf(plugin, "void dissect_%s(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)\n{\n", abbrev);
01039
01040 fprintf(plugin, "/** Set up structures needed to add the protocol subtree and manage it */\n");
01041 fprintf(plugin, "\tproto_item *tree_item;\n\tproto_tree *%s_tree;\n\tguint16 code;\n", abbrev);
01042
01043 for (map<string, vector<FieldInfo> >::iterator itr = fiMap->begin();
01044 itr != fiMap->end();
01045 itr++)
01046 {
01047 fprintf(plugin, "\tstatic struct {\n");
01048 for (i = 0; i < (*itr).second.size(); i++)
01049 {
01050 if (((*itr).second)[i].bitByte == FieldType::BIT)
01051 fprintf(plugin, "\t\tguint32 ");
01052 else
01053 fprintf(plugin, "\t\tguint8 *");
01054 fprintf(plugin, "%s_%s;\n", abbrev, ((*itr).second)[i].identifier);
01055 }
01056 fprintf(plugin, "\t} msg_%s;\n\n", (*itr).first.c_str());
01057 }
01058
01059 fprintf(plugin, "/** Make entries in Protocol column and Info column on summary display */\n");
01060 fprintf(plugin, "\tif (check_col(pinfo->cinfo, COL_PROTOCOL))\n");
01061 fprintf(plugin, "\t\tcol_set_str(pinfo->cinfo, COL_PROTOCOL, \"%s\");\n\n", ABBREV);
01062
01063 fprintf(plugin, "/** Verify the message sent and dissect it properly */\n");
01064 fprintf(plugin, "\tif (tree) {\n");
01065 fprintf(plugin, "\t\tcode = tvb_get_ntohs(tvb, 0);\n\n");
01066
01067 fprintf(plugin, "\t\ttree_item = proto_tree_add_item(tree, proto_%s, tvb, 0, -1, FALSE);\n", abbrev);
01068 fprintf(plugin, "\t\t%s_tree = proto_item_add_subtree(tree_item, ett_%s);\n\n", abbrev, abbrev);
01069
01070 fprintf(plugin, "\t\tif (");
01071
01072 for (map<string, vector<FieldInfo> >::iterator itr = fiMap->begin();
01073 itr != fiMap->end();
01074 itr++)
01075 {
01076 if (itr != fiMap->begin())
01077 fprintf(plugin, "\t\telse if (");
01078 vector <FieldInfo> temp = ((*itr).second);
01079 IntegerLiteral *msgCode = dynamic_cast<IntegerLiteral*> (temp[temp.size() - 1].init);
01080 fprintf(plugin, "code == %d)\n\t\t{\n", msgCode->getValue());
01081 fprintf(plugin, "\t\t\tint offset = 2; //sizeof(code) == 2 since code is a guint16 :)\n\n");
01082
01084 for (i = 0; i < (*itr).second.size() - 1; i++)
01085 {
01086 FieldInfo fi = (*itr).second[i];
01087
01088 if (fi.bitByte == FieldType::BIT)
01089 {
01090 int value = (dynamic_cast<IntegerLiteral*> (fi.size))->getValue();
01091
01092 if (value <= 8)
01093 {
01094 fprintf(plugin, "\t\t\tmsg_%s.%s_%s = tvb_get_guint8(tvb, offset);\n",
01095 (*itr).first.c_str(), abbrev, fi.identifier);
01096 fprintf(plugin, "\t\t\tproto_tree_add_item(%s_tree, hf_%s.%s_%s, tvb, offset, 1, FALSE);\n",
01097 abbrev, (*itr).first.c_str(), abbrev, fi.identifier);
01098 fprintf(plugin, "\t\t\toffset++;\n\n");
01099 }
01100 else if (value <= 16)
01101 {
01102 fprintf(plugin, "\t\t\tmsg_%s.%s_%s = tvb_get_ntohs(tvb, offset);\n",
01103 (*itr).first.c_str(), abbrev, fi.identifier);
01104 fprintf(plugin, "\t\t\tproto_tree_add_item(%s_tree, hf_%s.%s_%s, tvb, offset, 2, FALSE);\n",
01105 abbrev, (*itr).first.c_str(), abbrev, fi.identifier);
01106 fprintf(plugin, "\t\t\toffset += 2;\n\n");
01107 }
01108 else if (value <= 32 || value > 16)
01109 {
01110 fprintf(plugin, "\t\t\tmsg_%s.%s_%s = tvb_get_ntohl(tvb, offset);\n",
01111 (*itr).first.c_str(), abbrev, fi.identifier);
01112 fprintf(plugin, "\t\t\tproto_tree_add_item(%s_tree, hf_%s.%s_%s, tvb, offset, 4, FALSE);\n",
01113 abbrev, (*itr).first.c_str(), abbrev, fi.identifier);
01114 fprintf(plugin, "\t\t\toffset += 4;\n\n");
01115 }
01116 }
01117 else if (fi.bitByte == FieldType::BYTE &&
01118 typeid(*(fi.size)) == typeid(IntegerLiteral))
01119 {
01120 int value = (dynamic_cast<IntegerLiteral*> (fi.size))->getValue();
01121
01122 fprintf(plugin, "\t\t\tmsg_%s.%s_%s = tvb_memdup(tvb, offset, %d);\n",
01123 (*itr).first.c_str(), abbrev, fi.identifier, value);
01124 fprintf(plugin, "\t\t\tproto_tree_add_string(%s_tree, hf_%s.%s_%s, tvb, offset, %d, msg_%s.%s_%s);\n",
01125 abbrev, (*itr).first.c_str(), abbrev, fi.identifier, value, (*itr).first.c_str(), abbrev, fi.identifier);
01126 fprintf(plugin, "\t\t\toffset += %d;\n\n", value);
01127 }
01128 else if (fi.bitByte == FieldType::BYTE &&
01129 typeid(*(fi.size)) == typeid(Identifier))
01130 {
01131 const char *name = (dynamic_cast<Identifier*>(fi.size))->getName().c_str();
01132
01133 fprintf(plugin, "\t\t\tmsg_%s.%s_%s = tvb_memdup(tvb, offset, msg_%s.%s_%s);\n",
01134 (*itr).first.c_str(), abbrev, fi.identifier, (*itr).first.c_str(),
01135 abbrev, name);
01136 fprintf(plugin, "\t\t\tproto_tree_add_string(%s_tree, hf_%s.%s_%s, tvb, offset, msg_%s.%s_%s, msg_%s.%s_%s);\n",
01137 abbrev, (*itr).first.c_str(), abbrev, fi.identifier, (*itr).first.c_str(), abbrev, name,
01138 (*itr).first.c_str(), abbrev, fi.identifier);
01139 fprintf(plugin, "\t\t\toffset += msg_%s.%s_%s;\n\n", (*itr).first.c_str(), abbrev, name);
01140 }
01141 }
01142
01143 fprintf(plugin, "\t\t}\n");
01144 }
01145 fprintf(plugin, "\t}\n");
01146 fprintf(plugin, "}\n\n");
01147 }
01148
01149
01150 static void writeRest(FILE *plugin, char *trans, char *port, char *abbrev)
01151 {
01152 char *rest = "\n\n/* If this dissector uses sub-dissector registration add a registration routine.\n\
01153 This format is required because a script is used to find these routines and\n\
01154 create the code that calls these routines.\n\
01155 */\n";
01156
01157 fprintf(plugin, "%s", rest);
01158 fprintf(plugin, "void proto_reg_handoff_%s(void)\n{\n", abbrev);
01159 fprintf(plugin, "\tdissector_handle_t %s_handle;\n\n", abbrev);
01160
01161 fprintf(plugin, "\t%s_handle = create_dissector_handle(dissect_%s,\n\t\tproto_%s);\n", abbrev, abbrev, abbrev);
01162 fprintf(plugin, " dissector_add(\"%s.port\", %s, %s_handle);\n", trans, port, abbrev);
01163
01164 rest = "}\n\
01165 \n\
01166 #ifndef __ETHEREAL_STATIC__\n\
01167 G_MODULE_EXPORT void plugin_init(plugin_address_table_t *pat)\n\
01168 {\n\
01169 /* initialise the table of pointers needed in Win32 DLLs */\n\
01170 plugin_address_table_init(pat);\n\
01171 \n\
01172 /* register the new protocol, protocol fields, and subtrees */\n";
01173 fprintf(plugin, "%s", rest);
01174 fprintf(plugin, "\tif (proto_%s == -1) /* execute protocol initialization only once */\n", abbrev);
01175 fprintf(plugin, "\t\tproto_register_%s();\n}\n", abbrev);
01176 rest = "#endif\n\
01177 \n\
01178 #ifndef __ETHEREAL_STATIC__\n\
01179 G_MODULE_EXPORT void plugin_reg_handoff(void)\n\
01180 {\n\
01181 proto_reg_handoff_";
01182 fprintf(plugin, "%s%s();\n}\n#endif\n", rest, abbrev);
01183 }