]> andersk Git - splint.git/blob - src/lh.c
05930e84ac93b37bad17b9c43f28c62b90626792
[splint.git] / src / lh.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** lh.c
26 **
27 **  MODULE DESCRIPTION:
28 **
29 **      This module contains the I/O routines for writing out the .lh file
30 **      generated from the .lcl file.
31 **
32 **  AUTHORS:
33 **
34 **      Gary Feldman, Technical Languages and Environments, DECspec project
35 **      Yang Meng Tan, MIT.
36 **
37 **  CREATION DATE:  9 April 91
38 **
39 **      The lh.c module controls formatting policy.
40 */
41
42 # include "splintMacros.nf"
43 # include "llbasic.h"
44 # include "osd.h"
45 # include "lh.h"
46 # include "llmain.h"
47
48 /*@constant static char TABCH; @*/
49 # define TABCH          ' '
50
51 /*@constant static char TABINCH; @*/
52 # define TABINCH        '\t'
53
54
55 /*@private@*/ typedef struct
56 {
57   /*:open:*/ /*@dependent@*/ /*@null@*/ /*@reldef@*/ FILE *f;
58   /*@reldef@*/ cstring name;
59 } outFile;
60
61 static bool genLh;
62 static outFile LhFile;
63 static bool needIncludeBool = FALSE;
64
65 /*
66 **
67 **  FORWARD FUNCTIONS
68 **
69 */
70
71 /* static int colpos (int startcol, cstring line); */
72
73 static cstring lhTypeSpecNode (lclTypeSpecNode p_typespec);
74 static /*@only@*/ cstring lhTypeExpr (/*@null@*/ typeExpr p_x);
75 static /*@only@*/ cstring lhDeclaratorNode (declaratorNode p_x);
76
77 /*@only@*/ cstring 
78 lhFunction (lclTypeSpecNode lclTypeSpec, declaratorNode declarator)
79 {
80   cstring s;
81
82   if (!genLh)
83     return cstring_undefined;
84   
85   s = message ("extern %q %q;", lhTypeSpecNode (lclTypeSpec),
86                lhDeclaratorNode (declarator));
87   
88   return s;
89 }
90
91 static /*@only@*/ cstring
92 lhDeclaratorNode (declaratorNode x)
93 {
94   return (lhTypeExpr (x->type));
95 }
96
97 static /*@only@*/ cstring lhTypeExpr (/*@null@*/ typeExpr x)
98 {
99   cstring s = cstring_undefined; /* print out types in order of appearance in source */
100   paramNodeList params;
101   int i;
102
103   if (x != (typeExpr) 0)
104     {
105       cstring front = cstring_undefined;
106       cstring back  = cstring_undefined;
107
108       for (i = x->wrapped; i >= 1; i--)
109         {
110           front = cstring_appendChar (front, '(');
111           back  = cstring_appendChar (back, ')');
112         }
113
114       switch (x->kind)
115         {
116         case TEXPR_BASE:
117           s = message ("%q%s", s, ltoken_getRawString (x->content.base));
118           break;
119         case TEXPR_PTR:
120           s = message ("%q*%q", s, lhTypeExpr (x->content.pointer));
121           break;
122         case TEXPR_ARRAY:
123           s = message ("%q%q[%q]", s, 
124                        lhTypeExpr (x->content.array.elementtype),
125                        termNode_unparse (x->content.array.size));
126           break;
127         case TEXPR_FCN:
128           s = message ("%q%q (", s, lhTypeExpr (x->content.function.returntype));
129           params = x->content.function.args;
130
131           if (!paramNodeList_empty (params))
132             {
133               s = message ("%q%q", s, 
134                            paramNodeList_unparseComments (x->content.function.args));
135             }
136
137           s = message ("%q)", s);
138           break;
139         }
140       s = message ("%q%q%q", front, s, back);
141     }
142   else
143     {
144       s = cstring_makeLiteral ("?");
145     }
146
147   return s;
148 }
149
150 extern void
151 lhForwardStruct (ltoken t)
152 {
153   if (!genLh)
154     return;
155
156   lhOutLine (message ("struct %s;", ltoken_unparse (t)));
157 }
158
159
160 extern void
161 lhForwardUnion (ltoken t)
162 {
163   if (!genLh)
164     return;
165
166   lhOutLine (message ("union %s;", ltoken_unparse (t)));
167 }
168
169 extern /*@only@*/ cstring 
170 lhType (typeNode t)
171 {
172   if (!genLh)
173     return cstring_undefined;
174
175   if (t->kind == TK_EXPOSED)
176     {
177       exposedNode n = t->content.exposed;
178
179       if (n != (exposedNode) 0)
180         {
181           if (declaratorInvNodeList_size (n->decls) == 0)
182             {
183               /* 
184               ** Forward struct or union declaration
185               */
186
187               return (cstring_appendChar (lhTypeSpecNode (n->type), ';'));
188             }
189           else
190             {
191               cstring s = cstring_undefined;
192
193               declaratorInvNodeList_elements (n->decls, d)
194                 {
195                   cstring name = declaratorNode_unparse (d->declarator);
196                   cstring pname = declaratorNode_unparseCode (d->declarator); 
197                   
198                   s = message ("%q\n# ifndef EXPOSED_TYPE_%q\ntypedef %q %q;\n# endif\n", 
199                                s, pname, lhTypeSpecNode (n->type), name);
200                 } end_declaratorInvNodeList_elements;
201               
202               return s;
203             }
204         }
205     }
206
207   return cstring_undefined;
208 }
209
210 static /*@only@*/ cstring 
211 lhTypeSpecNode (lclTypeSpecNode typespec)
212 {
213   if (!genLh)
214     {
215       return cstring_undefined;
216     }
217
218   return (lclTypeSpecNode_unparseComments (typespec));
219 }
220
221 /*@only@*/ cstring
222 lhVarDecl (lclTypeSpecNode lclTypeSpec, initDeclNodeList initDecls,
223            qualifierKind qualifier)
224 {
225   bool first = TRUE;
226   cstring s;
227
228   if (!genLh)
229     return cstring_undefined;
230
231   s = cstring_makeLiteral ("extern");
232
233   switch (qualifier)
234     {
235     case QLF_NONE:
236       break;
237     case QLF_CONST:
238       s = message ("%q const", s);
239       break;
240     case QLF_VOLATILE:
241       s = message ("%q volatile", s);
242       break;
243     default:                    /* ignore it */
244       break;
245     }
246   
247   s = message ("%q %q ", s, lhTypeSpecNode (lclTypeSpec));
248
249   initDeclNodeList_elements (initDecls, i)
250   {
251     if (first)
252       {
253         s = message ("%q %q", s, declaratorNode_unparse (i->declarator));
254         first = FALSE;
255       }
256     else
257       {
258         s = message ("%q, %q", s, declaratorNode_unparse (i->declarator));
259       }
260   } end_initDeclNodeList_elements;
261   
262   return (message ("%q;", s));
263 }
264
265 extern void
266 lhCleanup (void)
267    /*@modifies fileSystem@*/
268 {
269   if (!genLh)
270     {
271       return;
272     }
273   else
274     {
275       llassert (LhFile.f != NULL);
276       
277       if (LhFile.f == NULL)
278         {
279           /*@i25534  check this!  does it report the right filename? */
280           lldiagmsg (message ("Cannot open lh file for output: %s", LhFile.name));
281         }
282       else
283         {
284           check (fprintf (LhFile.f, "/* Output from %s */\n", LCL_PARSE_VERSION) > 0);
285           check (fileTable_closeFile (context_fileTable (), LhFile.f));
286           LhFile.f = NULL;
287         }
288     }
289 }
290
291 /* Write an #include of bool.h if we have't done so already.  */
292 extern void
293 lhIncludeBool (void)
294 {
295   needIncludeBool = TRUE;
296 }
297
298 void lhInit (inputStream f) /*@globals undef LhFile; @*/
299 {
300   static bool lherror = FALSE;
301   
302   genLh = context_msgLh ();
303   needIncludeBool = FALSE;
304
305   if (!genLh)
306     {
307       return;
308     }
309   
310   LhFile.name = cstring_concatFree1 (LSLRootName (inputStream_fileName (f)),
311                                      LH_EXTENSION);
312   LhFile.f = fileTable_openWriteUpdateFile (context_fileTable (), LhFile.name);
313
314   if (LhFile.f == NULL)
315     {
316       genLh = FALSE;
317       if (!lherror)
318         {
319           lclplainerror (message ("Cannot write temporary file: %s", 
320                                   LhFile.name));
321           lherror = TRUE;
322         }
323     } 
324
325
326 void lhOutLine (/*@only@*/ cstring s)
327 {
328   if (genLh)
329     {
330       llassert (LhFile.f != NULL);
331       DPRINTF (("lhOutLine: %s / %s", s, LhFile.name));
332
333       if (cstring_length (s) > 0) 
334         {
335           check (fputs (cstring_toCharsSafe (s), LhFile.f) != EOF); 
336         }
337
338       check (fputc ('\n', LhFile.f) == (int) '\n'); 
339     }
340
341   cstring_free (s);
342 }
343
344 void lhExternals (interfaceNodeList x)
345 {
346   if (genLh)
347     {
348       llassert (LhFile.f != NULL);
349
350       /*
351       ** Need to make sure all standard library includes come first.
352       */
353
354       interfaceNodeList_elements (x, el)
355         {
356           if (el->kind == INF_IMPORTS)
357             {
358               importNodeList imps = el->content.imports;
359
360               importNodeList_elements (imps, il)
361                 {
362                   if (il->kind == IMPBRACKET)
363                     {
364                       lhOutLine (message ("# include <%s.h>", 
365                                           ltoken_getRawString (il->val)));
366                     }
367                 } end_importNodeList_elements ;
368             }
369         } end_interfaceNodeList_elements;
370
371       lhOutLine (cstring_makeLiteral ("# include \"bool.h\""));
372       
373       interfaceNodeList_elements (x, el)
374         {
375           if (el->kind == INF_IMPORTS)
376             {
377               importNodeList imps = el->content.imports;
378
379               importNodeList_elements (imps, il)
380                 {
381                   if (il->kind != IMPBRACKET)
382                     {
383                       lhOutLine (message ("# include \"%s.h\"", 
384                                           ltoken_getRawString (il->val)));
385                     }
386                 } end_importNodeList_elements ;
387             }
388         } end_interfaceNodeList_elements;
389
390       lhOutLine (cstring_undefined);
391     }
392 }
393
394
395
This page took 0.054074 seconds and 3 git commands to generate.