/tags/rel-1-3-15/SWIG/Source/Modules1.1/contract.cxx
C++ | 118 lines | 82 code | 18 blank | 18 comment | 9 complexity | 7f408ce03cb7abad10faabe1a638bfb3 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
1/* -----------------------------------------------------------------------------
2 * contract.cxx
3 *
4 * Experimental support for contracts
5 *
6 * Author(s) : Aquinas Hobor (aahobor@cs.uchicago.edu)
7 *
8 * Copyright (C) 1999-2000. The University of Chicago
9 * See the file LICENSE for information on usage and redistribution.
10 * ----------------------------------------------------------------------------- */
11
12static char cvsroot[] = "$Header$";
13
14#include "swigmod.h"
15
16class Contracts : public Dispatcher {
17
18public:
19 virtual int top(Node *n) {
20 emit_children(n);
21 return SWIG_OK;
22 }
23
24 virtual int importDirective(Node *n) { return emit_children(n); }
25 virtual int includeDirective(Node *n) { return emit_children(n); } // ?
26 virtual int externDeclaration(Node *n) { return emit_children(n); }
27
28 String * strParms(ParmList *l) {
29 int comma = 0;
30 int i = 0;
31 Parm *p = l;
32 SwigType *pt;
33 String * returns = NewString("");
34 while(p) {
35 String *pname;
36 pt = Getattr(p,"type");
37 if ((SwigType_type(pt) != T_VOID)) {
38 if (comma) Printf(returns,",");
39 pname = Swig_cparm_name(p,i);
40 Printf(returns,"%s",SwigType_rcaststr(pt,pname));
41 comma = 1;
42 i++;
43 }
44 p = nextSibling(p);
45 }
46 return returns;
47 }
48
49 virtual int cDeclaration(Node *n) {
50 String *name = Getattr(n,"name");
51 String *k = Getattr(n,"feature:contract");
52
53 if(k)
54 {
55 /* make the names */
56 ParmList *l = Getmeta(k,"parms");
57 String *params = ParmList_str(l);
58 String *transformed = strParms(l);
59 if(DohStrcmp(params,"")==0) {
60 DohDelete(params);
61 params = DohNewString("void");
62 }
63 String *contractName = DohNewStringf("__SWIG_precontract_%s",name);
64
65 /* make the contract */
66 String *contract = DohNewStringf("int %s(%s,int rt[2])\n{\n",contractName,params);
67 SwigScanner * ss = NewSwigScanner();
68 SwigScanner_clear(ss);
69 SwigScanner_push(ss,Copy(k));
70 SwigScanner_token(ss); // Get rid of the '{' at the begining
71
72 /* loop over the clauses */
73 int clauseNum = 1;
74 int token = -1;
75 while(1) {
76 String *clause = DohNewString(""); /*BUG -- should free*/
77 while((token=SwigScanner_token(ss))) {
78 if ((token==SWIG_TOKEN_SEMI)||(token==SWIG_TOKEN_RBRACE))
79 break;
80 // if (token != SWIG_TOKEN_ENDLINE)
81 Printf(clause,"%s",SwigScanner_text(ss));
82 }
83 if (DohStrcmp(clause,"\n") != 0) {
84 Printf(contract,"if (!(%s",clause);
85 Printf(contract,")) {\nrt[0]=__LINE__;\nrt[1]=%i;\nreturn 1;\n}\n",clauseNum);
86 }
87 if(token==SWIG_TOKEN_RBRACE) break;
88 clauseNum++;
89 }
90
91 /* finish it off and attach it to the main tree */
92 Printf(contract,"return 0;\n}\n");
93 Setattr(n,"wrap:code",contract); /*BUG -- WHAT IF SOMETHING IS ALREADY THERE*/
94
95 /* Generate the calling code */
96 String * calling = DohNewString("{\nint cfail[2];\nchar message[255];\n");
97 Printf(calling,"if (%s(%s,cfail)) {\n",contractName,transformed);
98 Printf(calling,"sprintf(message,\"Contract %s failed on clause %%i (line %%i)!\",cfail[1],cfail[0]);\n",contractName);
99 Printf(calling,"PyErr_SetString(PyExc_Exception,message);return NULL;\n}\n");
100 Printf(calling,"}\n");
101 /* Setattr(n,"feature:preassert",calling); */
102 }
103 /*There are two attributes "feature:preassert" and "feature:postassert".*/
104
105
106 return SWIG_OK;
107 }
108
109};
110
111void Swig_contracts(Node *n) {
112 Printf(stdout,"Applying contracts (experimental v0.09)\n");
113
114 Contracts *a = new Contracts;
115 a->top(n);
116 delete a;
117
118}