]> andersk Git - splint.git/blob - src/source.c
*** empty log message ***
[splint.git] / src / source.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
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 "lclintMacros.nf"
48 # include "llbasic.h"
49 # include "osd.h"
50 # include "portab.h"
51
52 extern bool
53 inputStream_close (inputStream s)
54 {
55   if (s->file != NULL)
56     {
57       check (fclose (s->file) == 0);
58       s->file = NULL;
59       return TRUE;
60     }
61
62   return FALSE;
63 }
64
65 extern void
66 inputStream_free (/*@null@*/ /*@only@*/ inputStream s)
67 {
68   if (s != NULL)
69     {
70       sfree (s->name);
71       sfree (s->stringSource);
72       sfree (s->curLine);
73       sfree (s);
74     }
75 }
76
77 extern /*@only@*/ inputStream 
78   inputStream_create (char *name, char *suffix, bool echo)
79 {
80   char *ps;
81   inputStream s = (inputStream) dmalloc (sizeof (*s));
82   
83   s->name = (char *) dmalloc (strlen (name) + strlen (suffix) + 1);
84   s->file = 0;
85   strcpy (s->name, name);
86
87   ps = strrchr (s->name, CONNECTCHAR);
88
89   if (ps == (char *) 0)
90     {
91       ps = s->name;
92     }
93
94   if (strchr (ps, '.') == NULL)
95     {
96       strcat (s->name, suffix);
97     }
98
99   s->lineNo = 0;
100   s->charNo = 0;
101   s->curLine = NULL;
102   s->echo = echo;
103   s->fromString = FALSE;
104   s->stringSource = NULL;
105   s->stringSourceTail = NULL;
106   
107   return s;
108 }
109
110 extern /*@only@*/ inputStream 
111 inputStream_fromString (char *name, char *str)
112 {
113   inputStream s = (inputStream) dmalloc (sizeof (*s));
114
115   s->name = mstring_copy (name);
116   s->stringSource = mstring_copy (str);
117   s->stringSourceTail = s->stringSource;
118   s->file = 0;
119   s->echo = FALSE;
120   s->fromString = TRUE;
121   s->lineNo = 0;
122   s->charNo = 0;
123   s->curLine = NULL;
124
125   return s;
126 }
127
128 extern int inputStream_nextChar (inputStream s)
129 {
130   int res = inputStream_peekChar (s);
131
132   if (res != EOF) 
133     {
134       if (res == '\n')
135         {
136           s->curLine = NULL;
137           s->charNo = 0;
138         }
139       else
140         {
141           s->charNo++;
142         }
143     }
144
145   DPRINTF (("Next char: %c [%d]", res, res));
146   return res;
147 }
148
149 extern int inputStream_peekNChar (inputStream s, int n)
150      /* Doesn't work across lines! */
151 {
152   llassert (s->curLine != NULL);
153   llassert (s->charNo + n < strlen (s->curLine));
154   return ((int) s->curLine [s->charNo + n]);
155 }
156
157 extern int inputStream_peekChar (inputStream s)
158 {  
159   if (s->curLine == NULL)
160     {
161       s->curLine = NULL;
162       s->curLine = inputStream_nextLine (s);
163       s->charNo = 0;
164     }
165
166   if (s->curLine == NULL)  
167     {
168       return EOF;
169     }
170  
171   llassert (s->charNo <= strlen (s->curLine));
172
173   if (s->curLine[s->charNo] == '\0') 
174     {
175       return '\n';
176     }
177  
178   return ((int) s->curLine [s->charNo]);
179
180
181 extern /*@dependent@*/ /*@null@*/ 
182 char *inputStream_nextLine (inputStream s)
183 {
184   char *currentLine;
185   int len;
186
187   llassert (s->curLine == NULL);
188   s->charNo = 0;
189
190   if (s->fromString)
191     {
192       if (s->stringSourceTail == NULL || (strlen (s->stringSourceTail) == 0))
193         {
194           currentLine = 0;
195         }
196       else
197         {
198           char *c = strchr (s->stringSourceTail, '\n');
199           
200           
201           /* in case line is terminated not by newline */ 
202           if (c == 0)
203             {
204               c = strchr (s->stringSourceTail, '\0');
205             }
206
207           len = c - s->stringSourceTail + 1;
208
209           if (len > STUBMAXRECORDSIZE - 2)
210             {
211               len = (STUBMAXRECORDSIZE - 2);
212             }
213
214           currentLine = &(s->buffer)[0];
215           strncpy (currentLine, s->stringSourceTail, size_fromInt (len));
216           currentLine[len] = '\0';
217           s->stringSourceTail += len;
218         }
219       
220     }
221   else
222     {
223       llassert (s->file != NULL);
224       currentLine = fgets (&(s->buffer)[0], STUBMAXRECORDSIZE, s->file);
225     }
226   if (currentLine == 0)
227     {
228       strcpy (s->buffer, "*** End of File ***");
229     }
230   else
231     {
232       s->lineNo++;
233       len = strlen (currentLine) - 1;
234       if (s->buffer[len] == '\n')
235         {
236           s->buffer[len] = '\0';
237         }
238       else 
239         {
240           if (len >= STUBMAXRECORDSIZE - 2)
241             {
242               lldiagmsg (message ("Input line too long: %s",
243                                   cstring_fromChars (currentLine)));
244             }
245         }
246     }
247
248   /* if (s->echo) slo_echoLine (currentLine);           only needed in LCL */
249   return currentLine;
250 }
251
252 extern bool
253 inputStream_open (inputStream s)
254 {
255   if (s->fromString)
256     {
257       /* not an error: tail is dependent */
258       s->stringSourceTail = s->stringSource; 
259       return TRUE;
260     }
261
262   DPRINTF (("Open: %s", s->name));
263   s->file = fopen (s->name, "r");
264   return (s->file != 0 || s->fromString);
265 }
266
267 /*
268 ** requires
269 **  path != NULL \and
270 **  s != NULL \and
271 **  *s.name == filename (*s.name) || filetype (*s.name)
272 **      *s.name consists of a file name and type only ("<filename>.<type>)
273 **      No path name is included
274 **
275 ** ensures
276 **  if filefound (*path, *s) then
277 **      result = true \and *s.name = filespec_where_file_found (*path, *s)
278 **  else
279 **      result = false
280 */
281
282 extern bool inputStream_getPath (char *path, inputStream s)
283 {
284   char *returnPath;
285   filestatus status;            /* return status of osd_getEnvPath.*/
286   bool rVal;                    /* return value of this procedure. */
287
288  /* Check if requires met. */
289   if (path == NULL || s == NULL || s->name == NULL)
290     {
291       llbugexitlit ("inputStream_getPath: invalid parameter");
292     }
293
294   status = osd_getPath (path, s->name, &returnPath);
295
296   if (status == OSD_FILEFOUND)
297     {                           /* Should be majority of cases. */
298       rVal = TRUE;
299       
300       sfree (s->name);
301       s->name = returnPath;
302     }
303   else if (status == OSD_FILENOTFOUND)
304     {
305       rVal = FALSE;
306     }
307   else if (status == OSD_PATHTOOLONG)
308     {
309       rVal = FALSE;
310      /* Directory and filename are too long.  Report error. */
311      llbuglit ("soure_getPath: Filename plus directory from search path too long");
312  }
313   else
314     {
315       rVal = FALSE;
316       llbuglit ("inputStream_getPath: invalid return status");
317     }
318   return rVal;
319 }
320
321 # ifndef NOLCL
322 char *specFullName (char *specfile, /*@out@*/ char **inpath)
323 {
324   /* extract the path and the specname associated with the given file */
325   char *specname = (char *) dmalloc (sizeof (*specname) 
326                                      * (strlen (specfile) + 9));
327   char *ospecname = specname;
328   char *path = (char *) dmalloc (sizeof (*path) * (strlen (specfile)));
329   size_t size;
330   long int i, j;
331   
332   /* initialized path to empty string or may have accidental garbage */
333   *path = '\0';
334
335   /*@-mayaliasunique@*/ 
336   strcpy (specname, specfile);
337   /*@=mayaliasunique@*/ 
338
339   /* trim off pathnames in specfile */
340   size = strlen (specname);
341
342   for (i = size_toInt (size) - 1; i >= 0; i--)
343     {
344       if (specname[i] == CONNECTCHAR)
345         {
346           /* strcpy (specname, (char *)specname+i+1); */
347           for (j = 0; j <= i; j++)      /* include '/'  */
348             {
349               path[j] = specname[j];
350             }
351
352           path[i + 1] = '\0';
353           specname += i + 1;
354           break;
355         }
356     }
357
358   /* 
359   ** also remove .lcl file extension, assume it's the last extension
360   ** of the file name 
361   */
362
363   size = strlen (specname);
364
365   for (i = size_toInt (size) - 1; i >= 0; i--)
366     {
367       if (specname[i] == '.')
368         {
369           specname[i] = '\0';
370           break;
371         }
372     }
373   
374   *inpath = path;
375
376   /*
377   ** If specname no longer points to the original char,
378   ** we need to allocate a new pointer and copy the string.
379   */
380
381   if (specname != ospecname) {
382     char *rspecname = (char *) dmalloc (sizeof (*rspecname) * (strlen (specname) + 1));
383     strcpy (rspecname, specname); /* evs 2000-05-16: Bug: was ospecname! */
384     sfree (ospecname);
385     return rspecname;
386   } 
387
388   return specname;
389 }
390 # endif
391
This page took 0.067197 seconds and 5 git commands to generate.