]> andersk Git - splint.git/blob - src/inputStream.c
95c1323462087e9341495061af323d538928bb19
[splint.git] / src / inputStream.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 ** source.c
26 **
27 ** Interface to source file abstraction
28 **
29 **      NOTE:       This module is almost identical to the one for LCL.  The
30 **                  only difference is that a couple of source lines have been
31 **                  commented out.
32 **
33 **                  This module has too many dependencies to be in the common
34 **                  source area.  Any of the solutions that would allow this
35 **                  module to be common had its own set of compromises.  It
36 **                  seemed best and most straightforward to just keep separte
37 **                  copies for LSL and LCL.  We should examine this again if we
38 **                  ever reorganize the module structure.
39 **
40 **  AUTHORS:
41 **
42 **     Steve Garland,
43 **         Massachusetts Institute of Technology
44 **     Joe Wild, Technical Languages and Environments, DECspec project
45 */
46
47 # include "splintMacros.nf"
48 # include "llbasic.h"
49 # include "osd.h"
50 # include "portab.h"
51
52 extern bool
53 inputStream_close (inputStream s)
54 {
55   llassert (inputStream_isDefined (s));
56
57   if (s->file != NULL)
58     {
59       check (fileTable_closeFile (context_fileTable (), s->file));
60       s->file = NULL;
61       return TRUE;
62     }
63
64   return FALSE;
65 }
66
67 extern void
68 inputStream_free (/*@null@*/ /*@only@*/ inputStream s)
69 {
70   if (inputStream_isDefined (s))
71     {
72       cstring_free (s->name);
73       cstring_free (s->stringSource);
74       sfree (s);
75     }
76 }
77
78 extern /*@only@*/ inputStream 
79 inputStream_create (cstring name, cstring suffix, bool echo)
80 {
81   char *ps;
82   inputStream s = (inputStream) dmalloc (sizeof (*s));
83   cstring oname;
84
85   s->name = name;
86   s->file = NULL;
87
88   /*@access cstring@*/
89   llassert (cstring_isDefined (s->name));
90   /*@i534 clean this up...*/
91   ps = strrchr (s->name, CONNECTCHAR);
92
93   if (ps == NULL)
94     {
95       ps = s->name;
96     }
97   /*@noaccess cstring@*/
98
99   if (strchr (ps, '.') == NULL)
100     {
101       s->name = cstring_concatFree1 (s->name, suffix);
102     }
103
104   oname = s->name;
105   s->name = fileLib_cleanName (s->name);
106   /*@i523@*/ cstring_free (oname); /* evans 2002-07-12: why no error without this?! */
107
108   s->lineNo = 0;
109   s->charNo = 0;
110   s->curLine = NULL;
111   s->echo = echo;
112   s->fromString = FALSE;
113   s->stringSource = NULL;
114   s->stringSourceTail = NULL;
115   s->buffer[0] = '\0';
116
117   /*@i523@*/ return s;
118 }
119
120 extern /*@only@*/ inputStream 
121 inputStream_fromString (cstring name, cstring str)
122 {
123   inputStream s = (inputStream) dmalloc (sizeof (*s));
124
125   s->name = cstring_copy (name);
126   s->stringSource = cstring_copy (str);
127   s->stringSourceTail = s->stringSource;
128   s->file = 0;
129   s->echo = FALSE;
130   s->fromString = TRUE;
131   s->lineNo = 0;
132   s->charNo = 0;
133   s->curLine = NULL;
134   s->buffer[0] = '\0';
135
136   return s;
137 }
138
139 extern int inputStream_nextChar (inputStream s)
140 {
141   int res;
142
143   llassert (inputStream_isDefined (s));
144   res = inputStream_peekChar (s);
145
146   if (res != EOF) 
147     {
148       if (res == (int) '\n')
149         {
150           s->curLine = NULL;
151           s->charNo = 0;
152           incLine ();
153         }
154       else
155         {
156           s->charNo++;
157           incColumn ();
158         }
159     }
160
161   DPRINTF (("Next char: %c [%d]", (char) res, res));
162   return res;
163 }
164
165 extern int inputStream_peekNChar (inputStream s, int n)
166      /* Doesn't work across lines! */
167 {
168   llassert (inputStream_isDefined (s));
169   llassert (s->curLine != NULL);
170   llassert (s->charNo + n < strlen (s->curLine));
171   return ((int) s->curLine [s->charNo + n]);
172 }
173
174 extern int inputStream_peekChar (inputStream s)
175 {  
176   llassert (inputStream_isDefined (s));
177
178   if (s->curLine == NULL)
179     {
180       char *cur;
181       s->curLine = NULL;
182       cur = inputStream_nextLine (s);
183       s->curLine = cur; /* split this to avoid possible undefined behavior */
184       s->charNo = 0;
185     }
186
187   if (s->curLine == NULL)  
188     {
189       return EOF;
190     }
191  
192   llassert (s->charNo <= strlen (s->curLine));
193
194   if (s->curLine[s->charNo] == '\0') 
195     {
196       return (int) '\n';
197     }
198  
199   return ((int) s->curLine [s->charNo]);
200
201
202 extern /*@dependent@*/ /*@null@*/ 
203 char *inputStream_nextLine (inputStream s)
204 {
205   char *currentLine;
206   size_t len;
207
208   llassert (inputStream_isDefined (s));
209   llassert (s->curLine == NULL);
210   s->charNo = 0;
211
212   if (s->fromString)
213     {
214       if (cstring_isEmpty (s->stringSourceTail))
215         {
216           currentLine = 0;
217         }
218       else
219         {
220           /*@access cstring@*/
221           char *c = strchr (s->stringSourceTail, '\n');
222           
223           /* in case line is terminated not by newline */ 
224           if (c == 0)
225             {
226               c = strchr (s->stringSourceTail, '\0');
227             }
228
229           len = size_fromInt (c - s->stringSourceTail + 1);
230
231           if (len > size_fromInt (STUBMAXRECORDSIZE - 2))
232             {
233               len = size_fromInt (STUBMAXRECORDSIZE - 2);
234             }
235
236           currentLine = &(s->buffer)[0];
237           strncpy (currentLine, s->stringSourceTail, len);
238           currentLine[len] = '\0';
239           s->stringSourceTail += len;
240           /*@noaccess cstring@*/
241         }
242       
243     }
244   else
245     {
246       llassert (s->file != NULL);
247       currentLine = fgets (&(s->buffer)[0], STUBMAXRECORDSIZE, s->file);
248     }
249   if (currentLine == 0)
250     {
251       strcpy (s->buffer, "*** End of File ***");
252     }
253   else
254     {
255       s->lineNo++;
256       len = strlen (currentLine) - 1;
257       if (s->buffer[len] == '\n')
258         {
259           s->buffer[len] = '\0';
260         }
261       else 
262         {
263           if (len >= size_fromInt (STUBMAXRECORDSIZE - 2))
264             {
265               lldiagmsg (message ("Input line too long: %s",
266                                   cstring_fromChars (currentLine)));
267             }
268         }
269     }
270
271   /* if (s->echo) slo_echoLine (currentLine);           only needed in LCL */
272   return currentLine;
273 }
274
275 extern bool
276 inputStream_open (inputStream s)
277 {
278   llassert (inputStream_isDefined (s));
279   if (s->fromString)
280     {
281       /* not an error: tail is dependent */
282       s->stringSourceTail = s->stringSource; 
283       return TRUE;
284     }
285
286   DPRINTF (("Opening: %s", s->name));
287   s->file = fileTable_openReadFile (context_fileTable (), s->name);
288   return (s->file != 0 || s->fromString);
289 }
290
291 /*
292 ** requires
293 **  path != NULL \and
294 **  s != NULL \and
295 **  *s.name == filename (*s.name) || filetype (*s.name)
296 **      *s.name consists of a file name and type only ("<filename>.<type>)
297 **      No path name is included
298 **
299 ** ensures
300 **  if filefound (*path, *s) then
301 **      result = true \and *s.name = filespec_where_file_found (*path, *s)
302 **  else
303 **      result = false
304 */
305
306 extern bool inputStream_getPath (cstring path, inputStream s)
307 {
308   cstring returnPath;
309   filestatus status;            /* return status of osd_getEnvPath.*/
310   bool rVal;                    /* return value of this procedure. */
311   
312   llassert (cstring_isDefined (path));
313   llassert (inputStream_isDefined (s));
314   llassert (cstring_isDefined (s->name));
315
316   status = osd_getPath (path, s->name, &returnPath);
317
318   if (status == OSD_FILEFOUND)
319     {                           /* Should be majority of cases. */
320       rVal = TRUE;
321       
322       cstring_free (s->name);
323       s->name = fileLib_cleanName (returnPath);
324     }
325   else if (status == OSD_FILENOTFOUND)
326     {
327       rVal = FALSE;
328     }
329   else if (status == OSD_PATHTOOLONG)
330     {
331       rVal = FALSE;
332      /* Directory and filename are too long.  Report error. */
333      llbuglit ("soure_getPath: Filename plus directory from search path too long");
334  }
335   else
336     {
337       rVal = FALSE;
338       llbuglit ("inputStream_getPath: invalid return status");
339     }
340
341   return rVal;
342 }
343
344 /*:open:*/ FILE *inputStream_getFile (inputStream s)
345 {
346   llassert (inputStream_isDefined (s));
347   llassert (s->file != NULL);
348   return s->file;
349 }
350
351 cstring inputStream_fileName (inputStream s)
352 {
353   llassert (inputStream_isDefined (s));
354   return s->name;
355 }
356
357 bool inputStream_isOpen (inputStream s)
358 {
359   return (inputStream_isDefined (s) && (s->file != 0 || s->fromString));
360 }
361
362 int inputStream_thisLineNumber (inputStream s)
363 {
364   llassert (inputStream_isDefined (s));
365   return s->lineNo;
366 }
367
368
369
370
This page took 0.05938 seconds and 3 git commands to generate.