001/**************************************************************************** 002 * Copyright/Copyleft: 003 * 004 * For this source the LGPL Lesser General Public License, 005 * published by the Free Software Foundation is valid. 006 * It means: 007 * 1) You can use this source without any restriction for any desired purpose. 008 * 2) You can redistribute copies of this source to everybody. 009 * 3) Every user of this source, also the user of redistribute copies 010 * with or without payment, must accept this license for further using. 011 * 4) But the LPGL is not appropriate for a whole software product, 012 * if this source is only a part of them. It means, the user 013 * must publish this part of source, 014 * but don't need to publish the whole source of the own product. 015 * 5) You can study and modify (improve) this source 016 * for own using or for redistribution, but you have to license the 017 * modified sources likewise under this LGPL Lesser General Public License. 018 * You mustn't delete this Copyright/Copyleft inscription in this source file. 019 * 020 * @author Hartmut Schorrig: hartmut.schorrig@vishia.de, www.vishia.org 021 * @version 0.93 2011-01-05 (year-month-day) 022 *******************************************************************************/ 023package org.vishia.java2C; 024 025 026/**This class holds the data of one variable in a local context respectively a field of a class, 027 * see {@link LocalIdents} 028 * or describe the access to a instance, see {@link CCodeData}. 029 */ 030public class FieldData 031{ 032 /**version, history and license. 033 * <ul> 034 * <li>2014-09-05 Hartmut new: {@link #modeAccess} can have value 'M' for a PtrVal access. Regarded for C-generation. 035 * <li>2008 Hartmut created: 036 * </ul> 037 * 038 * <b>Copyright/Copyleft</b>: 039 * For this source the LGPL Lesser General Public License, 040 * published by the Free Software Foundation is valid. 041 * It means: 042 * <ol> 043 * <li> You can use this source without any restriction for any desired purpose. 044 * <li> You can redistribute copies of this source to everybody. 045 * <li> Every user of this source, also the user of redistribute copies 046 * with or without payment, must accept this license for further using. 047 * <li> But the LPGL is not appropriate for a whole software product, 048 * if this source is only a part of them. It means, the user 049 * must publish this part of source, 050 * but don't need to publish the whole source of the own product. 051 * <li> You can study and modify (improve) this source 052 * for own using or for redistribution, but you have to license the 053 * modified sources likewise under this LGPL Lesser General Public License. 054 * You mustn't delete this Copyright/Copyleft inscription in this source file. 055 * </ol> 056 * If you are intent to use this sources without publishing its usage, you can get 057 * a second license subscribing a special contract with the author. 058 * 059 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 060 * 061 * 062 */ 063 public final static String sVersion = "2014-09-05"; 064 065 066 /**The name of the identifier. <code>null</code> if it is the description of an access to an unnamed instance. */ 067 private final String sName; 068 069 /**The type respectively reference type of the field. */ 070 public final ClassData typeClazz; 071 072 /**The type of a key if it is a generic container type of keys and values. Elsewhere null. */ 073 public ClassData keyClazz; 074 075 /**The type of a elements of a generic container type. Elsewhere null. */ 076 public ClassData elementClazz; 077 078 /**If this field is set, the instance referenced in the described field is guaranteed an instance 079 * of that type, nor from a derived type. It means, no dynamic linked call is necessary, 080 * methods can called static using this instance type. This property saves some calculation times, 081 * while calling override-able methods of the referenced class. 082 * <br> 083 * If references are used as interface references for Java test and software design (including 084 * the documentation aspect), but the implementation uses the named instance in any case, 085 * this feature should be used. 086 * <br> 087 * For a reference variable this behavior is possible to control with @ java2c=instanceType:TYPE. 088 * This behavior is also set at embedded instance automatically. 089 * This field is null, if the instance isn't predefined. 090 */ 091 public final ClassData instanceClazz; 092 093 /**The class where the identifier is member of, null if it is a local identifier. */ 094 public final ClassData declaringClazz; 095 096 /**Char to indicate the location and kind of definition. 097 * <ul><li>'S' static constant 098 * <li>'s' static non constant 099 * <li>'d' immediate constant with define 100 * <li>'n' stack-locally Field which stores a reference to a new created instance, to activate for garbage collection. 101 * <li>'r' nonPersistent. 102 * <li>'t' not used, TODO used 'r' String, which may be non persistent. Maybe return value with buffer in Thread-Context. 103 * <li>'.' non static, no special functionality. 104 * </ul> 105 */ 106 public final char modeStatic; 107 108 /**If the identifier is an array with fix size, programmed in java in form of 109 * <pre> 110 * Type[][] myArray = new Type[expr][expr]; 111 * </pre> 112 * The <code>expr</code> translated in C-Form are stored here. This expr should be a simple value 113 * in C. There are used to generate the initialization of an array. 114 * <br> 115 * <code>null</code> if it isn't an array or it is a dynamic array. 116 */ 117 public final String[] fixArraySizes; 118 119 /**0 if it isn't an array. 1.. if it is an array. 120 * if modeArrayElement=='B' it is the fix size of a StringBuffer with direct char*. 121 */ 122 private final int dimensionArrayOrFixSize; 123 124 125 /**Kind of the access to an element, if it is an array. 126 * The adequate chars are used see {@link #modeAccess}. 127 * Special case: If it is 'B', the field describes a <code>StringBufferJc</code> with a fix size. 128 * In that case the {@link #dimensionArrayOrFixSize} contains the number of chars inclusive the 4 chars 129 * storing in the <code>StringBufferJc</code>-instance with immediate buffer. 130 */ 131 public final char modeArrayElement; 132 133 /**Kind of the instance. For non-arrays: 134 * <table> 135 * <tr><td>$</td><td>an embedded struct</td></tr> 136 * <tr><td>%</td><td>a variable of basic primitive type such as int32, float, char, 137 * but also an embedded indivisible struct like StringJc, MemC, OS_TimeStamp, 138 * whose elements aren't accessed in Java. </td></tr> 139 * <tr><td>*</td><td>a simple reference, pointer in C, used for non-GC-controlled associations.</td></tr> 140 * <tr><td>@</td><td>an enhanced reference, for GC (garbage collector) -controlled associations.</td></tr> 141 * <tr><td>m</td><td>an method table-reference.</td></tr> 142 * <tr><td>t</td><td>a StringJc, it is an enhanced reference ~REF also, but with special accesses</td></tr> 143 * <tr><td>&</td><td>an method-table reference ~MTB, containing C-jump-table with index. 144 * This type is only used for stack-local variables. GC is not possible</td></tr> 145 * <tr><td>~</td><td>ythis as reference (call own method</td></tr> 146 * <tr><td>+</td><td>A variable argument list</td></tr> 147 * </table> 148 * if {@link #dimensionArrayOrFixSize} >0, this element describes the access to the array head. 149 * The kind of elements respectively the access to the data of the elements are described in {@link #modeArrayElement}. 150 * with the same key chars as shown above. Independent of the kind of referencing the array 151 * the elements may be embedded struct ('$'), references ('*') etc., see {@link #modeArrayElement}. 152 * <table> 153 * <tr><td>M</td><td>Reference to an array with a PtrVal in C. A PtrVal is a <code>struct { Type* ptr__; int32 value__}</code> 154 * whereby <code>Type</code> is the type of the reference. The <code>value__</code> contains the number of elements 155 * of the array. The array is 1-dimensional. 156 * In Java it is any array <code>@Java4C=PtrVal Type[]</code>. 157 * <tr><td>B</td><td>A ByteStringJc. It is similar as StringJc, but it references bytes, not chars. 158 * In Java it is a byte[] with java2c=ByteStringJc-designation. 159 * Hint: A ByteStringJc is designated in this class with {@link #dimensionArrayOrFixSize}=1. 160 * It is an array with 1 dimension. 161 * It is similar MemC (pointer to memory and size). </td></tr> 162 * <tr><td>P</td><td>A simple reference to the array elements without head, pointer in C, 163 * used for non-GC-controlled associations.</td></tr> 164 * <tr><td>Q</td><td>An embedded array without head. All elements are embedded. 165 * The {@link #fixArraySize} is set.</td></tr> 166 * <tr><td>X</td><td>A simple reference to <code>ObjectArrayJc</code> head informations, pointer in C, to an array type, used for non-GC-controlled associations.</td></tr> 167 * <tr><td>Y</td><td>An embedded array with <code>ObjectArrayJc</code> head informations. 168 * All elements are embedded. The {@link #fixArraySize} is set.</td></tr> 169 * <tr><td>@</td><td>an enhanced reference to an array type, starting with ObjectArrayJc, 170 * for GC (garbage collector) -controlled associations.</td></tr> 171 * </table> 172 */ 173 public final char modeAccess; 174 175 /**see {@link getClassLevel()}*/ 176 int nClassLevel; 177 178 /**see {@link getOuterLevel()}. Note: this private member is set in the outer class, 179 * see {@link putClassElement(String, String, ClassData, String, ClassData)} 180 * or {@link putLocalElement(String, String, ClassData, String)} 181 */ 182 int nOuterLevel; 183 184 /**Name of an associated StringBuilder. 185 * It is relevant only if the field is a StringJc-variable and it is temporary. */ 186 String sStringBuilderName; 187 188 /**initializes the instance node. */ 189 FieldData 190 ( String sName 191 , ClassData typeClazz 192 , ClassData instanceClass 193 , ClassData elementClass 194 , ClassData keyClass 195 , char staticMode 196 , char accessMode 197 , int dimensionArray 198 , String[] fixArraySizes 199 , char modeArrayElement 200 , ClassData declaringClazz 201 ) 202 { this.sName = sName; 203 if(sName !=null && sName.equals("rxBuffer")) 204 stop(); 205 if(instanceClass!=null && instanceClass.sClassNameJava.equals("AnswerComm_ifc")) 206 stop(); 207 assert(".?%*~$&@mXYPQMt+B".indexOf(accessMode)>=0); 208 this.modeAccess = accessMode; 209 //this.sModifier = sModifier; 210 this.fixArraySizes = fixArraySizes; 211 this.declaringClazz = declaringClazz; 212 if(typeClazz==null) throw new IllegalArgumentException("typeClazz = null for:" + sName); 213 214 this.typeClazz = typeClazz; 215 this.instanceClazz = instanceClass; 216 this.elementClazz = elementClass; 217 this.keyClazz = keyClass; 218 this.dimensionArrayOrFixSize = dimensionArray; //NOTE: if modeArrayElement=='B' it is the fix size of a StringBuffer 219 //assert(dimensionArray == 0 || dimensionArray == 1); 220 if(modeArrayElement == '$') 221 stop(); 222 assert(".%t*$&@B".indexOf(modeArrayElement)>=0); 223 this.modeArrayElement = modeArrayElement; 224 assert("sSdrn.".indexOf(staticMode)>=0); 225 this.modeStatic = staticMode; 226 } 227 228 229 230 231 232 /**Copies given FieldData, but modify with given parameters 233 * @param parent //the parent 234 * @param classLevelAdd Adds the class level, 0: keep from parent. To copy instances for super classes 235 * @param outerLevelAdd Adds the outer level, 0: keep from parent. To copy instances for inner classes 236 * @param modeAccessP if '.' than keep parent.modeAccess, else take that. 237 */ 238 FieldData(FieldData parent, int classLevelAdd, int outerLevelAdd, char modeAccessP, char modeStaticP) 239 { this.sName = parent.sName; 240 if(sName.equals("searchTrc") )//&& outerLevelAdd == 1) 241 stop(); 242 this.modeAccess = modeAccessP == '.' ? parent.modeAccess : modeAccessP; 243 this.declaringClazz = parent.declaringClazz; 244 this.typeClazz = parent.typeClazz; 245 this.instanceClazz = parent.instanceClazz; 246 this.keyClazz = parent.keyClazz; 247 this.elementClazz = parent.elementClazz; 248 this.dimensionArrayOrFixSize = parent.dimensionArrayOrFixSize; 249 this.fixArraySizes = parent.fixArraySizes; 250 this.modeArrayElement = parent.modeArrayElement; 251 this.modeStatic = modeStaticP=='.' ? parent.modeStatic: modeStaticP; 252 this.nClassLevel = parent.nClassLevel + classLevelAdd; 253 this.nOuterLevel = parent.nOuterLevel + outerLevelAdd; 254 } 255 256 257 /* 258 FieldData(FieldData parent, int dimensionArrayOrFixSize) 259 { //this.sTypeIdent = parent.sTypeIdent; 260 this.sName = parent.sName; 261 this.modeAccess = parent.modeAccess; 262 //this.sModifier = sModifier; 263 this.fixArraySizes = parent.fixArraySizes; 264 this.clazz = parent.clazz; 265 this.typeClazz = parent.typeClazz; 266 this.dimensionArray = (byte)dimensionArrayOrFixSize; 267 this.modeArrayElement = parent.modeArrayElement; 268 this.modeStatic = parent.modeStatic; 269 } 270 */ 271 272 /**level of the affiliation to a class in the inheritance level. 273 * 0= it is a local visible variable. 1=element of this class, 2=element of super class etc. 274 */ 275 public int getClassLevel(){ return nClassLevel; } 276 277 278 /**Returns 0 if it isn't an array, 1.. for number of array dimension.*/ 279 public int getDimensionArray(){ return ".B".indexOf(modeArrayElement) <0 ? dimensionArrayOrFixSize : 0; } 280 281 282 /**Returns the size >0 if the type is a StringBuffer with a immediate String with fix size, else 0. 283 */ 284 public int getFixSizeStringBuffer(){return modeArrayElement=='B'? dimensionArrayOrFixSize : 0; } 285 286 /**level of the affiliation to a class in the outer class relation. 287 * 0= it is a local visible variable. 1=element of this class, 2=element of outer class etc. 288 */ 289 public int getOuterLevel(){ return nOuterLevel; } 290 291 /**returns the name of the element. */ 292 public String getName(){ return sName; } 293 294 /**returns the name of the type of the element. */ 295 public String getTypeName(){ return typeClazz.getClassCtype_s(); } 296 297 public String getTypeChar() 298 { return "" + typeClazz.cVaArgIdent; 299 } 300 301 302 303 304 /**Generates the C type declaration appropriate to the type info in this FieldData. 305 * It is the type code used for definition of the variable. 306 * <ul> 307 * <li>Simple embedded Arrays: At example type int. It returns only <code>int</code> because 308 * the complete definition is <code>int name[123]</code> or <code>int name[] = { 1, 2, 3}</code> 309 * </ul> 310 * <br> 311 * If it is an simple array, the type code designating the pointer to the elements requires an additional '*' 312 * @return String with C type declaration. 313 */ 314 public String gen_Declaration(iWriteContent generateFile) 315 { final String sPreModifier; 316 if(sName != null && sName.equals("int32")) 317 stop(); 318 if(modeStatic == 'S') { 319 sPreModifier = "const "; 320 } else { 321 sPreModifier = ""; 322 } 323 final String sTypeReturn; // .sTypeIdent; 324 switch(modeAccess) 325 { case 'B': 326 case '$': 327 case 't': 328 case '%': sTypeReturn = typeClazz.getClassCtype_s(); break; 329 case 'C': 330 case '*': { sTypeReturn = "struct " + typeClazz.getClassIdentName() 331 + (typeClazz.isConstant ? "_t const*":"_t*"); 332 generateFile.addStructForwardType(typeClazz); 333 } break; 334 case '@': sTypeReturn = typeClazz.getClassIdentName() + "REF"; break; 335 case '&': sTypeReturn = typeClazz.getClassIdentName() + "MTB"; break; 336 case '+': sTypeReturn = "char const*"; break; 337 case 'X': //reference to an ObjectArrayJc, reference or not of elements in modeArrayElement 338 sTypeReturn = typeClazz.getClassIdentName() + (typeClazz.isConstant ? "_Y const*":"_Y*"); break; 339 case 'Y': //instance of an ObjectArrayJc, reference or not of elements in modeArrayElement 340 sTypeReturn = typeClazz.getClassIdentName() + "_Y"; break; 341 case 'M': 342 sTypeReturn = "PtrVal_" + typeClazz.getClassIdentName(); break; 343 case 'P': 344 { switch(modeArrayElement) 345 { case '$': 346 case 't': 347 case '%': sTypeReturn = typeClazz.getClassCtype_s() + "*"; ; break; 348 case '*': sTypeReturn = "struct " + typeClazz.getClassIdentName() 349 + (typeClazz.isConstant ? "_t const**":"_t**"); break; 350 case '@': sTypeReturn = typeClazz.getClassIdentName() + "REF*"; break; 351 default: sTypeReturn = null; 352 } 353 } break; 354 case 'Q': 355 { /**embedded array. to use in declaration, at ex. int name[] is produced, here only int.*/ 356 switch(modeArrayElement) 357 { case '$': 358 case 't': 359 case '%': sTypeReturn = typeClazz.getClassCtype_s() + ""; ; break; 360 case '*': sTypeReturn = "struct " + typeClazz.getClassIdentName() 361 + (typeClazz.isConstant ? "_t const*":"_t*"); break; 362 case '@': sTypeReturn = typeClazz.getClassIdentName() + "REF"; break; 363 default: sTypeReturn = null; 364 } 365 } break; 366 default: sTypeReturn = null; 367 } 368 assert(sTypeReturn != null); 369 return sPreModifier + sTypeReturn; 370 371 } 372 373 /**generates the code for a variable definition of the given FieldInfo. 374 * @return code for definition of the variable, without ";" on end. 375 * This method is only called inside {@link GenerateClass#gen_variableDefinition(org.vishia.zbnf.ZbnfParseResultItem, org.vishia.zbnf.ZbnfParseResultItem, LocalIdents, java.util.List, char)} 376 * It supplies all informations which are able to gotten in this class. 377 */ 378 String gen_VariableDefinition(char intension, iWriteContent generateFile) 379 { 380 if(sName.equals("clazz")) 381 stop(); 382 383 final String sNameC = "Ssd".indexOf(modeStatic)>=0 384 ? sName + "_" + declaringClazz.getClassIdentName() 385 : sName; //static variable with _Classname 386 String typeCode = gen_Declaration(generateFile); 387 if(sName.equals("singleton")) 388 stop(); 389 String ret = "???"; 390 if(dimensionArrayOrFixSize >0) 391 { final String elementType; 392 switch(modeArrayElement) 393 { case '%': case 't': case '$': elementType = typeClazz.getClassCtype_s(); break; 394 case '*': elementType = "struct " + typeClazz.getClassIdentName() 395 + (typeClazz.isConstant ? "_t const*":"_t*"); break; 396 case '@': elementType = typeClazz.getClassIdentName() + "REF"; break; 397 case '&': elementType = typeClazz.getClassIdentName() + "MTB"; break; 398 case 'B': elementType =null; assert(modeAccess == '$'); break; 399 default: elementType =null; assert(false); 400 } 401 switch(modeAccess){ 402 case 'M': { 403 ret = "PtrVal_" + typeClazz.getClassIdentName() + " " + sNameC; 404 } break; 405 case 'B': { 406 ret = "ByteStringJc " + sNameC; 407 } break; 408 case 'Y': 409 { /**A fix size embedded array, but with head: */ 410 ret = "struct " + sNameC + "_Y {" 411 + " ObjectArrayJc head; " + elementType + " data[" + fixArraySizes[0] + "]; }" 412 + sNameC; //NOTE: the ";" after definition is set outside. 413 }break; 414 case 'Q': 415 { /**An simple fix embedded array: */ 416 if(fixArraySizes != null) 417 { ret = typeCode + " " + sNameC; 418 for(String fixArraySize: fixArraySizes) 419 { ret += "[" + fixArraySize + "]"; 420 } 421 } 422 else assert(false); //it have to be fixArraySizes! 423 }break; 424 case 'X': 425 { ret = typeCode + " " + sNameC; 426 //TODO arrays with more as one dimension. 427 } break; 428 case '$': 429 { 430 assert(modeArrayElement == 'B'); 431 { /**Its a fix String buffer. */ 432 ret = "struct SbY_" + sNameC + "_t {" 433 + " StringBufferJc sb; char _b[" + (dimensionArrayOrFixSize-4) + "]; }" 434 + sNameC; //NOTE: the ";" after definition is set outside. 435 436 } 437 438 }break; 439 case 'p': 440 case 'P':{ 441 ret = elementType+ "* " + sNameC; 442 } break; 443 default: assert(false); 444 } 445 } 446 else { 447 if(modeStatic == 'd'){ 448 ret = "#define " + sNameC + " " + fixArraySizes[0]; 449 } 450 else { 451 ret = typeCode + " " + sNameC; 452 if(modeAccess == '+'){ 453 ret += ", ..."; 454 } 455 } 456 } 457 return ret; 458 } 459 460 /**Writes the structure of this instance to a <code>*.stc</code>-file. 461 * It is an class level identifier, see {@link ClassData#classLevelIdents}, 462 * or a return type or argument of a method, 463 * because only for such FieldData this method is called. 464 * See {@link LocalIdents#writeStruct(int)} and {@link ClassData.Method#writeStruct()} 465 * @return The content to write to <code>*.stc</code>-file. The form of string is the same 466 * described in the syntax <code>Java2Cstc.zbnf</code>. 467 */ 468 public String xxxwriteStruct() 469 { 470 if(typeClazz == null) 471 assert(false); 472 if(typeClazz.sClassNameJava.equals("InnerTest")) 473 stop(); 474 475 476 477 String out = "field:{ "; 478 479 //out += typeClazz.sPackage; 480 ClassData outerClazz = typeClazz; //start with it. 481 while( (outerClazz = outerClazz.outerClazz) != null) 482 { //insert left: 483 //out += outerClazz.sClassNameJava + "." ; 484 stop(); 485 } 486 //out += typeClazz.sClassNameJava; 487 out += typeClazz.sClassNameJavaFullqualified; 488 489 if(keyClazz != null){ 490 out += "<" + keyClazz.sClassNameJavaFullqualified + "," + elementClazz.sClassNameJavaFullqualified + ">"; 491 } 492 else if(elementClazz != null){ 493 out += "<" + elementClazz.sClassNameJavaFullqualified + ">"; 494 } 495 496 if(instanceClazz != null){ 497 out += " (instance=" + instanceClazz.sClassNameJavaFullqualified + ")"; 498 } 499 out += " " 500 + modeAccess 501 + modeArrayElement 502 + modeStatic; 503 assert(typeClazz.sPackage.length() == 0 || typeClazz.sPackage.endsWith("/")); 504 if(modeArrayElement == 'B'){ 505 out += "-fixBufferSize[" + dimensionArrayOrFixSize + "]"; 506 } 507 else { 508 /**Array may be with fix size.Either show [??] per size or the size. */ 509 for(int ii=0; ii<dimensionArrayOrFixSize; ii++) 510 { final String sFixArraySize = 511 fixArraySizes == null ? "??" 512 : fixArraySizes[ii] == null ? "?" 513 : fixArraySizes[ii]; 514 out += "[" + sFixArraySize + "]"; 515 } 516 } 517 out += " "+ sName + "; "; 518 out += "/*info" 519 + dimensionArrayOrFixSize 520 + nClassLevel + nOuterLevel 521 + "*/ }"; 522 //if() 523 return out; 524 } 525 526 527 /**Writes the structure of this instance to a <code>*.stc</code>-file. 528 * It is an class level identifier, see {@link ClassData#classLevelIdents}, 529 * or a return type or argument of a method, 530 * because only for such FieldData this method is called. 531 * See {@link LocalIdents#writeStruct(int)} and {@link ClassData.Method#writeStruct()} 532 * @return The content to write to <code>*.stc</code>-file. The form of string is the same 533 * described in the syntax <code>Java2Cstc.zbnf</code>. 534 */ 535 public String writeStruct() 536 { 537 StringBuilder out = new StringBuilder(30); 538 if(typeClazz == null) 539 assert(false); 540 ClassData outerClazz = typeClazz; //start with it. 541 while( (outerClazz = outerClazz.outerClazz) != null) 542 { //insert left: 543 //out += outerClazz.sClassNameJava + "." ; 544 stop(); 545 } 546 //out += typeClazz.sClassNameJava; 547 out.append(typeClazz.sClassNameJavaFullqualified); 548 549 if(keyClazz != null){ 550 out.append("<" + keyClazz.sClassNameJavaFullqualified + "," + elementClazz.sClassNameJavaFullqualified + ">"); 551 } 552 else if(elementClazz != null){ 553 out.append("<" + elementClazz.sClassNameJavaFullqualified + ">"); 554 } 555 if(modeArrayElement != 'B'){ 556 /**Array may be with fix size.Either show [??] per size or the size. */ 557 for(int ii=0; ii<dimensionArrayOrFixSize; ii++) 558 { final String sFixArraySize = 559 fixArraySizes == null ? "??" 560 : fixArraySizes[ii] == null ? "?" 561 : fixArraySizes[ii]; 562 out.append( "[" + sFixArraySize + "]"); 563 } 564 } 565 //additional informations: 566 String sSeparator = "("; 567 if(instanceClazz != null){ 568 out.append(sSeparator).append( "instance=").append(instanceClazz.sClassNameJavaFullqualified); 569 sSeparator = ", "; 570 } 571 if(modeArrayElement == 'B'){ 572 out.append(sSeparator).append("fixBufferSize=").append(dimensionArrayOrFixSize ); 573 } 574 if(!sSeparator.equals("(")){ out.append(")");} //any content 575 576 out.append( " ") 577 .append( modeAccess) 578 .append( modeArrayElement) 579 .append( modeStatic); 580 //.append(" c").append(nClassLevel) 581 //.append(" o").append(nOuterLevel); 582 assert(typeClazz.sPackage.length() == 0 || typeClazz.sPackage.endsWith("/")); 583 out.append( " ").append(sName); 584 return out.toString(); 585 } 586 587 588 /**Tests whether a cast to the given FieldData type is necessary and executes it. 589 * The cast consists of two parts: 590 * <ul><li>cast of type, for example to a base class type or another cast-able type 591 * <li>cast of access, for example from an enhanced reference to the reference 592 * </ul> 593 * If srcType is the same as this, no cast occurs, the value is returned direct. 594 * If srcType is a derive-able type of this, the cast is get with TODO. 595 * <br><br> 596 * The cast of access is gotten calling {@link #testAndChangeAccess(char, String, char)}. 597 * <br><br> 598 * This method prepares the access to a value. For assignments this method is used too, but the assignment has to produce code for setting, 599 * see {@link StatementBlock#gen_AssignCheckCast(CCodeData, String, CCodeData)}. 600 * <br><br> 601 * 602 * @param srcType The type of the value 603 * @param value The value string. 604 * @return The value itself if no cast is necessary 605 * @param src The Expression with its type and access modes 606 * @param modeAccessDst A deviating mode of access for the destination or '.'. If '.', the {@link #modeAcess} 607 * of this is valid. 608 * @return String, either src.cCode if no cast is necessary, or the casted expression. 609 */ 610 public String testAndcast(CCodeData src, char modeAccessDst) 611 { if(src.cCode.equals("REFJc(ythis->implifc2)")) 612 stop(); 613 614 final String sRet; 615 if(modeAccessDst == '.'){ modeAccessDst = this.modeAccess; } 616 assert(modeAccessDst != '&' || src.modeAccess == '&'); //no access conversion to Type_MTB 617 if(false && modeAccessDst == '&'){ //it doesn't work anytime. 618 /**A method-table-reference is need: */ 619 /**TypeMTBL is need. */ 620 final String sSrc2; 621 switch(src.modeAccess){ 622 case '*': sSrc2 = src.cCode; break; 623 case '$': sSrc2 = "&(" + src.cCode + ")"; break; 624 default: sSrc2 = "XXX"; assert(false); 625 } 626 sRet = "(" + typeClazz.getClassIdentName() + "MTB)mtblRef_ObjectJc(&(" + sSrc2 627 + ")->base.object, sign_Mtbl_" + typeClazz.getClassIdentName() + ")"; 628 } else { 629 if( src.cCode.equals("null")) 630 { //a null-pointer should be compatible with all except StringJc. 631 if(typeClazz.bEmbedded && dimensionArrayOrFixSize == 0) { 632 //Any embedded type should have a null_Name-instance, that content is assigned. 633 sRet = "null_" + typeClazz.getClassIdentName(); 634 } else if(typeClazz.sClassNameC.equals("StringJc") 635 && dimensionArrayOrFixSize == 0 //if >0, it is a String[] referenced. 636 ) { 637 assert(false); //condition above is met. 638 sRet = "null_StringJc"; 639 } else if('B' == modeAccess){ 640 //a Byte-String represents a byte[], dimensionArrayOrFixSize =1 typical, not tested. 641 //extension for future: use 'B' for more direct referenced types of arrays, 642 //adequate to a MemC. 643 sRet = "null_OS_PtrValue"; 644 }else { 645 sRet = "null"; 646 } 647 } 648 else { 649 650 if(src.cCode.startsWith("requireWay1Sensor_iRequireMainController(broker, _thCxt)")) 651 stop(); 652 653 654 ClassData.CastInfo castInfo; 655 if( this.typeClazz == src.identInfo.typeClazz 656 || src.identInfo.typeClazz == CRuntimeJavalikeClassData.clazz_unknown //unknown type, don't cast, it is okay: 657 || src.modeAccess == '?' //unknown type, don't cast, it is okay: 658 || this.typeClazz == CRuntimeJavalikeClassData.clazz_unknown //unknown type, don't cast, it is okay: 659 || this.typeClazz == CRuntimeJavalikeClassData.clazz_void //void as argument is a void* 660 || this.typeClazz == CRuntimeJavalikeClassData.clazz_va_argRaw //any type is valid 661 ) { 662 sRet = testAndChangeAccess(modeAccessDst, src.cCode, src.modeAccess); 663 } 664 else if( (castInfo = src.identInfo.typeClazz.getCastInfoToType(typeClazz.sClassNameC)) != null 665 ||(castInfo = typeClazz.getCastInfoFromType(src.identInfo.typeClazz.sClassNameC)) != null 666 ){ 667 /**cast src to this type: */ 668 String sSrcCasted = testAndChangeAccess(castInfo.modeAccessSrc, src.cCode, src.modeAccess); 669 String sSrc1 = castInfo.pre + sSrcCasted + castInfo.post; 670 sRet = testAndChangeAccess(modeAccessDst, sSrc1, castInfo.modeAccessDst); 671 } 672 else if(src.modeAccess =='X' && this.typeClazz==CRuntimeJavalikeClassData.singleton.clazzMemC){ 673 /**Cast of a array to MemC: */ 674 sRet = testAndChangeAccess(modeAccessDst, "buildFromArrayX_MemC(&(" + src.cCode + ")->head) ", '$'); 675 } 676 else if(src.modeAccess =='Q' && this.typeClazz==CRuntimeJavalikeClassData.singleton.clazzMemC){ 677 /**Cast of a array to MemC: */ 678 sRet = testAndChangeAccess(modeAccessDst, "build_MemC(&(" + src.cCode + "), " + src.identInfo.dimensionArrayOrFixSize + ") ", '$'); 679 } 680 else if(src.modeAccess =='M' && this.typeClazz==CRuntimeJavalikeClassData.singleton.clazzMemC){ 681 /**A PtrVal is the same as MemC in C. */ 682 sRet = "build_MemC(" + src.cCode + ".ptr__, " + src.cCode + ".value__ )"; //hint: Usage of MemC instead PtrVal is an older form. pointer type is not precise. 683 } 684 else if(src.modeAccess =='Y' && this.typeClazz==CRuntimeJavalikeClassData.singleton.clazzMemC){ 685 /**Cast of a array to MemC: */ 686 sRet = testAndChangeAccess(modeAccessDst, "buildFromArrayY_MemC(&(" + src.cCode + ")->head) ", '$'); 687 } 688 else if(src.modeAccess =='X' && this.typeClazz==CRuntimeJavalikeClassData.clazzObjectJc){ 689 /**Cast of a array to Object reference: */ 690 sRet = testAndChangeAccess(modeAccessDst, "(" + src.cCode + ")->head.object", '$'); 691 } 692 else if(src.modeAccess =='Y' && this.typeClazz==CRuntimeJavalikeClassData.clazzObjectJc){ 693 /**Cast of a array to Object reference: */ 694 sRet = testAndChangeAccess(modeAccessDst, "(" + src.cCode + ").head.object", '$'); 695 } 696 else { 697 /**No castInfo, but the types are different. It is a derivation. */ 698 String sClassNameDst = typeClazz.sClassNameC; 699 if(typeClazz.isPrimitiveType()){ 700 String sSrcCasted = testAndChangeAccess('%', src.cCode, src.modeAccess); 701 sRet = "((/*J2C:cast% from "+src.identInfo.getTypeName()+"*/" + sClassNameDst + ")(" + sSrcCasted + "))"; 702 } 703 else if("t$".indexOf(typeClazz.classTypeInfo.modeAccess) >=0){ 704 /**The dst should be a value (embedded). */ 705 String sSrcCasted = testAndChangeAccess('$', src.cCode, src.modeAccess); 706 sRet = "((/*J2C:cast$ from "+src.identInfo.getTypeName()+"*/" + sClassNameDst + ")(" + sSrcCasted + "))"; 707 } 708 else { 709 /**Normal pointer cast. */ 710 String sSrcCasted = testAndChangeAccess('*', src.cCode, src.modeAccess); 711 sRet = "((/*J2C:cast from "+src.identInfo.getTypeName()+"*/" + sClassNameDst + "*)(" + sSrcCasted + "))"; 712 } 713 } 714 } 715 } 716 return sRet; 717 718 } 719 720 721 722 String testAndCastInitializer(CCodeData src) 723 { String sRet; 724 if( src.cCode.equals("null")) 725 { //a null-pointer should be compatible with all expect StringJc. 726 if(typeClazz.sClassNameC.equals("StringJc") 727 && dimensionArrayOrFixSize == 0 728 ) 729 { 730 sRet = "NULL_StringJc"; } 731 else { 732 sRet = "null"; } 733 } 734 else { 735 if(src.cCode.startsWith("xxx")) 736 stop(); 737 ClassData.CastInfo castInfo; 738 if( this.typeClazz == src.identInfo.typeClazz 739 || src.identInfo.typeClazz == CRuntimeJavalikeClassData.clazz_unknown //unknown type, don't cast, it is okay: 740 || src.modeAccess == '?' //unknown type, don't cast, it is okay: 741 || this.typeClazz == CRuntimeJavalikeClassData.clazz_unknown //unknown type, don't cast, it is okay: 742 || this.typeClazz == CRuntimeJavalikeClassData.clazz_void //void as argument is a void* 743 || this.typeClazz == CRuntimeJavalikeClassData.clazz_va_argRaw //any type is valid 744 ) { 745 sRet = src.cCode; 746 } else if( 747 (castInfo = typeClazz.getCastInitializerFromType(src.identInfo.typeClazz.sClassNameC)) != null 748 ||(castInfo = src.identInfo.typeClazz.getCastInfoToType(typeClazz.sClassNameC)) != null 749 ||(castInfo = typeClazz.getCastInfoFromType(src.identInfo.typeClazz.sClassNameC)) != null 750 ){ 751 if(castInfo.pre.equals("CONST_z_StringJc(")) 752 stop(); //TODO count number of chars. 753 sRet = castInfo.pre + src.cCode + castInfo.post; 754 } else{ 755 sRet = src.cCode + "/*J2C: no cast found from " + src.identInfo.typeClazz + "*/"; 756 } 757 } 758 return sRet; 759 } 760 761 762 763 /**Changes the access. 764 * The '@' is handled like '*', because the building of enhanced reference is done outside. 765 * @param modeAccessDst Necessary access, ones of chars <code>&*@~%?</code>, see {@link #modeAccess} 766 * @param sSrc1 The cCode of src 767 * @param modeAccessSrc Existing access of sSrc1 768 * @return 769 */ 770 public static String testAndChangeAccess(char modeAccessDst, String sSrc1, char modeAccessSrc) 771 { String sAccessParam; 772 if(modeAccessSrc == modeAccessDst || modeAccessSrc == '?' || modeAccessDst == '?' ) { 773 sAccessParam = sSrc1; 774 } else if("&".indexOf(modeAccessSrc)>=0 && "*~".indexOf(modeAccessDst)>=0) { 775 sAccessParam = " (" + sSrc1 + ".ref)"; 776 } 777 else if(modeAccessSrc == '@'){ 778 switch(modeAccessDst){ 779 case '@': sAccessParam = sSrc1; break; 780 case '*': case '~': sAccessParam = "REFJc(" + sSrc1 + ")"; break; 781 case '$': sAccessParam = "*(REFJc(" + sSrc1 + "))"; break; 782 default: sAccessParam = sSrc1; assert(false); 783 } 784 } 785 else if(modeAccessSrc == 'Q'){ //non-headed embedded array: int x[20] 786 switch(modeAccessDst){ 787 case 'P': case '*': sAccessParam = "&" + sSrc1 + "[0]"; break; //pointer to first element 788 //case 'M': sAccessParam = "build_MemC( &" + sSrc1 + "[0], sizeof( " + sSrc1 + " ))"; break; //pointer to first element 789 case 'M': sAccessParam = sSrc1; break; //pointer and length initializer. 790 default: sAccessParam = sSrc1; 791 throw new IllegalArgumentException("cannot assign access-type '" + modeAccessDst 792 + "' to access-type '" + modeAccessSrc + "'. Hint: @Java2C-Annotation to the elements correct?"); 793 } 794 } 795 796 797 else if("*~&".indexOf(modeAccessSrc)>=0 && "%$".indexOf(modeAccessDst)>=0) { 798 sAccessParam = "* (" + sSrc1 + ")"; 799 } else if("%$".indexOf(modeAccessSrc)>=0 && "@*~&".indexOf(modeAccessDst) >=0){ 800 sAccessParam = "& (" + sSrc1 + ")"; 801 } else if("*~&".indexOf(modeAccessSrc)>=0 && "*~&".indexOf(modeAccessDst) >=0){ 802 /**Reference and this-reference are compatible. */ 803 sAccessParam = sSrc1; 804 } else if("%$t".indexOf(modeAccessSrc)>=0 && "%$t".indexOf(modeAccessDst) >=0){ 805 /**embedded or primitive type are not different. */ 806 sAccessParam = sSrc1; 807 } else if(false && "%$t".indexOf(modeAccessSrc)>=0 && "X".indexOf(modeAccessDst) >=0){ 808 /**embedded or primitive type get from an array. */ 809 sAccessParam = sSrc1 + "->data[] /*TODO*/"; 810 } else if(false && "X".indexOf(modeAccessSrc)>=0 && "$".indexOf(modeAccessDst) >=0){ 811 /**embedded or primitive type get from an array. */ 812 sAccessParam = sSrc1 + "->data[] /*TODO1*/"; 813 } 814 else { 815 //assert(false); 816 sAccessParam = sSrc1 + "/*J2C-error testAndChangeAccess: " + modeAccessSrc + modeAccessDst + "*/"; 817 //sAccessParam = null; 818 } 819 return sAccessParam; 820 } 821 822 823 824 private String xxxtestAndcast(ClassData srcType, String value) 825 { String sRet; 826 if( value.equals("null")) 827 { //a null-pointer should be compatible with all expect StringJc. 828 if(typeClazz.sClassNameC.equals("StringJc") 829 && dimensionArrayOrFixSize == 0 830 ) 831 { 832 sRet = "null_StringJc"; } 833 else { 834 sRet = value; } 835 } 836 else 837 { //TODO may be some array tests 838 839 sRet = typeClazz.xxxtestAndcast(srcType, value, '.'); 840 } 841 return sRet; 842 } 843 844 845 /**builds a String representation especially to test under eclipse. */ 846 @Override 847 public String toString() 848 { String sRet = typeClazz.getClassIdentName() + " " + sName + " " + nClassLevel + nOuterLevel + modeAccess + "[" + modeArrayElement + "]" + modeStatic + nClassLevel + nOuterLevel 849 + (declaringClazz != null ? declaringClazz.sClassNameC : " -stacklocal"); 850 return sRet; 851 } 852 853 854 855 856 /**It's a debug helper. The method is empty, but it is a mark to set a breakpoint. */ 857 void stop() 858 { //debug 859 } 860 861 862 863 864 865}