View Javadoc

1   /***
2    * Cecilia ADL Compiler
3    * Copyright (C) 2006-2007 STMicroelectronics
4    *
5    * This library is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10   * This library is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   * Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public
16   * License along with this library; if not, write to the Free Software
17   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   *
19   * Contact: fractal@objectweb.org
20   *
21   * Author:Ali Erdem Ozcan
22   * Contributor: Alessio Pace
23   */
24  
25  package org.objectweb.fractal.cecilia.adl.idl.util;
26  
27  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.getContainedDefinition;
28  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.getContainedType;
29  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.getPrimitiveType;
30  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.hasVarParams;
31  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.isConstParameter;
32  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.isInOutParameter;
33  import static org.objectweb.fractal.cecilia.adl.idl.util.Util.isOutParameter;
34  
35  import org.objectweb.fractal.cecilia.adl.idl.ast.ArrayOf;
36  import org.objectweb.fractal.cecilia.adl.idl.ast.ComplexType;
37  import org.objectweb.fractal.cecilia.adl.idl.ast.Field;
38  import org.objectweb.fractal.cecilia.adl.idl.ast.IDLDefinition;
39  import org.objectweb.fractal.cecilia.adl.idl.ast.Method;
40  import org.objectweb.fractal.cecilia.adl.idl.ast.Parameter;
41  import org.objectweb.fractal.cecilia.adl.idl.ast.ParameterContainer;
42  import org.objectweb.fractal.cecilia.adl.idl.ast.PointerOf;
43  import org.objectweb.fractal.cecilia.adl.idl.ast.PrimitiveType;
44  import org.objectweb.fractal.cecilia.adl.idl.ast.Type;
45  import org.objectweb.fractal.cecilia.adl.idl.ast.PrimitiveType.PrimitiveTypeEnum;
46  
47  /**
48   * Utility class for C code generation.
49   */
50  public final class CUtil {
51  
52    private CUtil() {
53    }
54  
55    /**
56     * Returns the equivalent in C of the given primitive or complex type.
57     * 
58     * @param type the type
59     * @return the equivalent in C of the given primitive or complex type.
60     */
61    public static String buildComplexOrPrimitiveType(final Type type) {
62  
63      if (type == null) {
64        throw new IllegalArgumentException("Type argument can't be null");
65      }
66  
67      if (type instanceof ComplexType) {
68        final IDLDefinition containedDefinition = getContainedDefinition((ComplexType) type);
69        if (containedDefinition == null) {
70          throw new IllegalStateException(
71              "The ComplexType contains a null IDLDefinition ("
72                  + ((ComplexType) type).getName() + ")");
73        }
74        return containedDefinition.getName().replace('.', '_');
75      } else if (type instanceof PrimitiveType) {
76        return buildPrimitiveType((PrimitiveType) type);
77      } else {
78        throw new IllegalArgumentException("Invalid type");
79      }
80    }
81  
82    /**
83     * Returns the equivalent in C of the given type.
84     * 
85     * @param type the primitive type
86     * @return the equivalent in C of the given type.
87     */
88    public static String buildPrimitiveType(final PrimitiveType type) {
89      return buildPrimitiveType(getPrimitiveType(type));
90    }
91  
92    /**
93     * Returns the equivalent in C of the given type.
94     * 
95     * @param type the primitive type
96     * @return the equivalent in C of the given type.
97     */
98    public static String buildPrimitiveType(final PrimitiveTypeEnum type) {
99      return type.getCType();
100   }
101 
102   /**
103    * Returns the equivalent in C of the given return type.
104    * 
105    * @param type the type
106    * @return the equivalent in C of the given return type.
107    */
108   public static String buildReturnType(Type type) {
109     final StringBuffer result = new StringBuffer();
110     int nbPointer = 0;
111 
112     // A return type is an [ArrayOf](PointerOf)*(PrimitiveType|ComplexType)
113     if (type instanceof ArrayOf) {
114       nbPointer++;
115       type = getContainedType((ArrayOf) type);
116     }
117 
118     while (type instanceof PointerOf) {
119       nbPointer++;
120       type = getContainedType((PointerOf) type);
121     }
122 
123     result.append(buildComplexOrPrimitiveType(type));
124 
125     for (int i = 0; i < nbPointer; i++)
126       result.append('*');
127 
128     return result.toString();
129   }
130 
131   /**
132    * @param parameter the parameter definition to be built.
133    * @return the parameter definition in C
134    */
135   public static String buildParameter(final Parameter parameter) {
136     final StringBuilder result = new StringBuilder();
137     Type type = getContainedType(parameter);
138 
139     String arraySpec = "";
140     int nbPointer = 0;
141 
142     while (type instanceof ArrayOf) {
143       final String size = ((ArrayOf) type).getSize();
144       if (size != null) {
145         arraySpec = "[" + size + "]" + arraySpec;
146       } else {
147         arraySpec = "[]" + arraySpec;
148       }
149       type = getContainedType((ArrayOf) type);
150     }
151 
152     while (type instanceof PointerOf) {
153       nbPointer++;
154       type = getContainedType((PointerOf) type);
155     }
156 
157     if (isConstParameter(parameter)) {
158       result.append("const ");
159     }
160 
161     result.append(buildComplexOrPrimitiveType(type));
162 
163     for (int i = 0; i < nbPointer; i++)
164       result.append('*');
165     result.append(' ');
166 
167     if (isOutParameter(parameter) || isInOutParameter(parameter)) {
168       result.append("(*").append(parameter.getName()).append(')');
169     } else {
170       result.append(parameter.getName());
171     }
172     result.append(arraySpec);
173     return result.toString();
174   }
175 
176   /**
177    * Builds a definition suitable for inclusion e.g. in attribute initializers
178    * (routine similar to buildReturnType, but it handles arrays differently)
179    *
180    * @param type the type
181    * @return the definition in C
182    */
183   public static String buildDeclarationType(final Type type) {
184     final StringBuilder result = new StringBuilder();
185     Type type2 = type;
186 
187     String arraySpec = "";
188     int nbPointer = 0;
189 
190     while (type2 instanceof ArrayOf) {
191       final String size = ((ArrayOf) type2).getSize();
192       if (size != null) {
193         arraySpec = "[" + size + "]" + arraySpec;
194       } else {
195         arraySpec = "[]" + arraySpec;
196       }
197       type2 = getContainedType((ArrayOf) type2);
198     }
199 
200     while (type2 instanceof PointerOf) {
201       nbPointer++;
202       type2 = getContainedType((PointerOf) type2);
203     }
204 
205     result.append(buildComplexOrPrimitiveType(type2));
206 
207     for (int i = 0; i < nbPointer; i++)
208       result.append('*');
209     result.append(' ');
210 
211     result.append(arraySpec);
212     return result.toString();
213   }
214 
215   /**
216    * @param field the field of a record definition to be built.
217    * @return the field definition in C
218    */
219   public static String buildRecordField(final Field field) {
220     return buildRecordField(field, field.getName());
221   }
222 
223   /**
224    * @param field the field of a union definition to be built.
225    * @return the field definition in C
226    */
227   public static String buildUnionField(final Field field) {
228     return buildUnionField(field, field.getName());
229   }
230 
231   /**
232    * @return <code>true</code> if the IDL AST Node being a PrimitiveType is
233    *         also a C primitive data type.
234    */
235   public static boolean isIDLPrimitiveTypeAlsoCPrimitiveType(
236       final PrimitiveType type) {
237     final String primitiveTypeName = (type).getName();
238 
239     /* and if this field is neither STRING nor ANY */
240     if (primitiveTypeName.equals(PrimitiveType.PrimitiveTypeEnum.STRING.name())
241         || primitiveTypeName.equals(PrimitiveType.PrimitiveTypeEnum.ANY.name())) {
242       return false;
243     }
244 
245     return true;
246   }
247 
248   /**
249    * @param field the field of a record definition to be built.
250    * @param name the name of the field to use.
251    * @return the field definition in C
252    */
253   public static String buildRecordField(final Field field, final String name) {
254     final StringBuilder result = new StringBuilder();
255     Type type = getContainedType(field);
256 
257     boolean alreadyWrittenConst = false;
258 
259     /* if the field is of a Cecilia IDL primitive type */
260     if (Util.isPrimitiveType(type)) {
261 
262       if (isIDLPrimitiveTypeAlsoCPrimitiveType((PrimitiveType) type)) {
263 
264         /* and if the field has the 'const' qualifier */
265         if (Util.isConstField(field)) {
266           result.append("const ");
267           alreadyWrittenConst = true;
268         }
269       }
270 
271     }
272 
273     String arraySpec = "";
274     int nbPointer = 0;
275 
276     while (type instanceof ArrayOf) {
277       final String size = ((ArrayOf) type).getSize();
278       if (size != null) {
279         arraySpec = "[" + size + "]" + arraySpec;
280       } else {
281         arraySpec = "[]" + arraySpec;
282       }
283       type = getContainedType((ArrayOf) type);
284     }
285 
286     while (type instanceof PointerOf) {
287       nbPointer++;
288       type = getContainedType((PointerOf) type);
289     }
290 
291     result.append(buildComplexOrPrimitiveType(type));
292 
293     for (int i = 0; i < nbPointer; i++)
294       result.append('*');
295     result.append(' ');
296     if (Util.isConstField(field) && !alreadyWrittenConst) {
297       result.append("const ");
298     }
299     result.append(name).append(arraySpec);
300     return result.toString();
301   }
302 
303   /**
304    * @param field the field of a union definition to be built.
305    * @param name the name of the field to use.
306    * @return the field definition in C
307    */
308   public static String buildUnionField(final Field field, final String name) {
309     final StringBuilder result = new StringBuilder();
310     Type type = getContainedType(field);
311 
312     boolean alreadyWrittenConst = false;
313 
314     /* if the field is of a Cecilia IDL primitive type */
315     if (Util.isPrimitiveType(type)) {
316 
317       if (isIDLPrimitiveTypeAlsoCPrimitiveType((PrimitiveType) type)) {
318 
319         /* and if the field has the 'const' qualifier */
320         if (Util.isConstField(field)) {
321           result.append("const ");
322           alreadyWrittenConst = true;
323         }
324       }
325 
326     }
327 
328     String arraySpec = "";
329     int nbPointer = 0;
330 
331     while (type instanceof ArrayOf) {
332       final String size = ((ArrayOf) type).getSize();
333       if (size != null) {
334         arraySpec = "[" + size + "]" + arraySpec;
335       } else {
336         arraySpec = "[]" + arraySpec;
337       }
338       type = getContainedType((ArrayOf) type);
339     }
340 
341     while (type instanceof PointerOf) {
342       nbPointer++;
343       type = getContainedType((PointerOf) type);
344     }
345 
346     result.append(buildComplexOrPrimitiveType(type));
347 
348     for (int i = 0; i < nbPointer; i++)
349       result.append('*');
350     result.append(' ');
351     if (Util.isConstField(field) && !alreadyWrittenConst) {
352       result.append("const ");
353     }
354     result.append(name).append(arraySpec);
355     return result.toString();
356   }
357 
358   /**
359    * @param type the signature of the type to be included.
360    * @return the include definition in C for the given type.
361    */
362   public static String buildInclude(final String type) {
363     final StringBuilder result = new StringBuilder();
364     result.append("#include \"").append(type.replace('.', '/')).append(
365         ".idl.h\"").append("\n");
366     return result.toString();
367   }
368 
369   /**
370    * @param method the method definition
371    * @param pointer indicates whether the built string corresponds to a method
372    *            definition or to a method definition pointer.
373    * @return the method definition in C.
374    */
375   public static String buildMethodDefinition(final Method method,
376       final boolean pointer) {
377     return buildMethodDefinition(method, pointer, method.getName());
378   }
379 
380   /**
381    * Builds method with a specific name.
382    * 
383    * @param method the method definition
384    * @param pointer indicates whether the built string corresponds to a method
385    *            definition or to a method pointer definition.
386    * @param methodName the specific name to be used.
387    * @return the method definition in C.
388    */
389   public static String buildMethodDefinition(final Method method,
390       final boolean pointer, final String methodName) {
391     final StringBuilder result = new StringBuilder();
392 
393     result.append(buildReturnType(getContainedType(method)));
394 
395     result.append(" ");
396     if (pointer) result.append("(*");
397     result.append(methodName);
398     if (pointer) result.append(')');
399 
400     result.append("(void *_this");
401     for (final Parameter parameter : ((ParameterContainer) method)
402         .getParameters()) {
403       result.append(", ");
404       result.append(buildParameter(parameter));
405     }
406     if (hasVarParams(method)) {
407       result.append(", ...");
408     }
409     result.append(')');
410 
411     return result.toString();
412   }
413 }