Bug Summary

File:src/syscmd.c
Warning:line 96, column 12
Although the value stored to 's' is used in the enclosing expression, the value is never actually read from 's'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name syscmd.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/kfp/aldor/aldor/aldor/src -fcoverage-compilation-dir=/home/kfp/aldor/aldor/aldor/src -resource-dir /usr/local/lib/clang/18 -D PACKAGE_NAME="aldor" -D PACKAGE_TARNAME="aldor" -D PACKAGE_VERSION="1.4.0" -D PACKAGE_STRING="aldor 1.4.0" -D PACKAGE_BUGREPORT="aldor@xinutec.org" -D PACKAGE_URL="" -D PACKAGE="aldor" -D VERSION="1.4.0" -D YYTEXT_POINTER=1 -D HAVE_STDIO_H=1 -D HAVE_STDLIB_H=1 -D HAVE_STRING_H=1 -D HAVE_INTTYPES_H=1 -D HAVE_STDINT_H=1 -D HAVE_STRINGS_H=1 -D HAVE_SYS_STAT_H=1 -D HAVE_SYS_TYPES_H=1 -D HAVE_UNISTD_H=1 -D STDC_HEADERS=1 -D HAVE_LIBREADLINE=1 -D HAVE_READLINE_READLINE_H=1 -D HAVE_READLINE_HISTORY=1 -D HAVE_READLINE_HISTORY_H=1 -D USE_GLOOP_SHELL=1 -D GENERATOR_COROUTINES=0 -D HAVE_DLFCN_H=1 -D LT_OBJDIR=".libs/" -I . -D VCSVERSION="2c53e759f1e00e345f8b172e7139debda72fda13" -internal-isystem /usr/local/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-empty-body -Wno-enum-compare -Wno-missing-field-initializers -Wno-unused -Wno-unused-parameter -Wno-error=format -Wno-error=type-limits -Wno-error=strict-aliasing -Wno-sign-compare -Wno-error=shift-negative-value -Wno-error=clobbered -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2026-01-15-223856-845667-1 -x c syscmd.c
1/*****************************************************************************
2 *
3 * syscmd.c: System command processing.
4 *
5 * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org).
6 *
7 ****************************************************************************/
8
9#include "abnorm.h"
10#include "fint.h"
11#include "fintphase.h"
12#include "macex.h"
13#include "parseby.h"
14#include "scan.h"
15#include "stab.h"
16#include "syscmd.h"
17#include "util.h"
18#include "archive.h"
19#include "lib.h"
20#include "srcline.h"
21#include "comsg.h"
22#include "strops.h"
23#include "symbol.h"
24#include "ftype.h"
25
26/*****************************************************************************
27 *
28 * :: Parser/Handlers
29 *
30 ****************************************************************************/
31
32/*
33 * Handle all system commands, transforming the list.
34 */
35
36TokenList
37scmdProcessList(TokenList tl)
38{
39 struct TokenListCons head;
40 TokenList prev, curr;
41 Token tok;
42
43 setcar(&head, NULL)((&head)->first = (((void*)0)));
44 setcdr(&head, tl)((&head)->rest = (tl));
45
46 for (prev = &head; cdr(prev)((prev)->rest); ) {
47 curr = cdr(prev)((prev)->rest);
48 tok = car(curr)((curr)->first);
49
50 if (tokTag(tok)((TokenTag) (tok)->tag) != TK_SysCmd) {
51 prev = curr;
52 }
53 else {
54 tl = scmdProcessToken(tok);
55
56 if (tl) {
57 setcdr(listLastCons(Token)(tl), cdr(curr))(((Token_listPointer->LastCons)(tl))->rest = (((curr)->
rest)))
;
58 setcdr(prev, tl)((prev)->rest = (tl));
59 }
60 else
61 setcdr(prev, cdr(curr))((prev)->rest = (((curr)->rest)));
62
63 listFreeCons(Token)(Token_listPointer->FreeCons)(curr);
64 tokFree(tok);
65 }
66 }
67
68 return cdr(&head)((&head)->rest);
69}
70
71
72TokenList
73scmdProcessToken(Token tok)
74{
75 if (tokTag(tok)((TokenTag) (tok)->tag) != TK_SysCmd) return 0;
76
77 return scmdProcess(tok->pos, tok->val.str);
78}
79
80TokenList
81scmdProcessOrCheck(Bool doit, SrcPos spos, String cmd)
82{
83 String s, id, fname;
84 int rc = 0;
85 TokenList tl = 0;
86
87 if (scmdIsDirective(cmd, "")) {
88 /* Accept empty directive. */
89 }
90 else if ((s = scmdIsDirective(cmd, "pile")) != 0) {
91 if (doit) {
92 Token tok = tokKeyword(spos, spos, KW_StartPile)tokNew(spos, spos, KW_StartPile);
93 tl = listCons(Token)(Token_listPointer->Cons)(tok, NULL((void*)0));
94 }
95 }
96 else if ((s = scmdIsDirective(cmd, "endpile")) != 0) {
Although the value stored to 's' is used in the enclosing expression, the value is never actually read from 's'
97 if (doit) {
98 Token tok = tokKeyword(spos, spos, KW_EndPile)tokNew(spos, spos, KW_EndPile);
99 tl = listCons(Token)(Token_listPointer->Cons)(tok, NULL((void*)0));
100 }
101 }
102 else if ((s = scmdIsDirective(cmd, "library")) != 0) {
103 if (doit) {
104/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!
105 if ((s = scmdScanFName(s, &fname)) != 0)
106 rc = scmdHandleLibrary(NULL, fname);
107 else
108*/
109 if ((s = scmdScanId(s, &id)) != 0 &&
110 (s = scmdScanFName(s, &fname)) != 0)
111 rc = scmdHandleLibrary(id, fname);
112 if (!s || rc < 0)
113 comsgError(abNewNothing(spos)abNew(AB_Nothing, spos,0 ),
114 ALDOR_E_SysCmdBad42,"library");
115 }
116 }
117 else if ((s = scmdIsDirective(cmd, "libraryDir")) != 0) {
118 if (doit) {
119 if ((s = scmdScanFName(s, &fname)) != 0)
120 rc = scmdHandleLibraryDir(fname);
121 if (!s || rc < 0)
122 comsgError(abNewNothing(spos)abNew(AB_Nothing, spos,0 ),
123 ALDOR_E_SysCmdBad42,"libraryDir");
124 }
125 }
126 else if ((s = scmdIsDirective(cmd, "includeDir")) != 0) {
127 /*
128 * This ought to have been handled by "include". If
129 * we reach this point then surely something is wrong.
130 */
131 if (doit) {
132 if ((s = scmdScanFName(s, &fname)) != 0)
133 rc = scmdHandleIncludeDir(fname);
134 if (!s || rc < 0)
135 comsgError(abNewNothing(spos)abNew(AB_Nothing, spos,0 ),
136 ALDOR_E_SysCmdBad42, "includeDir" );
137 }
138 }
139 else if ((s = scmdIsDirective(cmd, "error")) != 0) {
140 if (doit)
141 comsgError(abNewNothing(spos)abNew(AB_Nothing, spos,0 ), ALDOR_E_ExplicitMsg1, s);
142 }
143 else if ((s = scmdIsDirective(cmd, "quit")) != 0) {
144 /* Doesn't make sense unless under the interpreter */
145 if (doit)
146 exitSuccess();
147 }
148 else if ((s = scmdIsDirective(cmd, "int")) != 0) {
149 if (doit) {
150 if (fintMode == FINT_LOOP2) fintParseOptions(s);
151 }
152 }
153#if OBSOLETE
154 else if ((s = scmdIsDirective(cmd, "syntax")) != 0) {
155 if (doit) {
156 printf("#syntax \"%s\"\n", s);
157 }
158 }
159 else if ((s = scmdIsDirective(cmd, "macro")) != 0) {
160 if (doit)
161 scmdHandleMacro(spos, s);
162 }
163#endif
164 else {
165 comsgWarning(abNewNothing(spos)abNew(AB_Nothing, spos,0 ), ALDOR_W_SysCmdUnknown43);
166 }
167
168 return tl;
169}
170
171TokenList
172scmdProcess(SrcPos spos, String cmd)
173{
174 return scmdProcessOrCheck(true1, spos, cmd);
175}
176
177void
178scmdCheck(SrcPos spos, String cmd)
179{
180 scmdProcessOrCheck(false((int) 0), spos, cmd);
181}
182
183
184/*****************************************************************************
185 *
186 * :: Scanners
187 *
188 ****************************************************************************/
189
190/*
191 * If the line is the right kind of command return the tail, otherwise 0.
192 */
193localstatic String
194restIfCmd(String ln, String kword, Bool isAbbrev)
195{
196 String s;
197
198 /* We are guaranteed that *ln is a directive character. */
199 ln++;
200
201 /* Specially handle test for empty command. */
202 if (!*kword) {
203 if (*ln == '!') return ln+1; /* #!...\n */
204 while (*ln && isspace(*ln)((*__ctype_b_loc ())[(int) ((*ln))] & (unsigned short int
) _ISspace)
) ln++; /* # \n */
205 if (!*ln) return ln;
206 return 0;
207 }
208
209 /* Allow spaces before the directive name. */
210 while (*ln && isspace(*ln)((*__ctype_b_loc ())[(int) ((*ln))] & (unsigned short int
) _ISspace)
) ln++;
211
212 /* Check that the directive name is a prefix of ln. */
213 s = strIsPrefix(kword, ln);
214 if (s == 0) return 0;
215
216 /* Skip to end of word, if kword is an abbreviation. */
217 if (isAbbrev) while (*s && !isspace(*s)((*__ctype_b_loc ())[(int) ((*s))] & (unsigned short int)
_ISspace)
) s++;
218
219 /* If there is nothing left, return the empty tail. */
220 if (!*s) return s;
221
222 /* Otherwise space after the directive name. */
223 if (!isspace(*s)((*__ctype_b_loc ())[(int) ((*s))] & (unsigned short int)
_ISspace)
) return 0;
224
225 return s;
226}
227
228String
229scmdIsAbbrev(String ln, String kword)
230{
231 return restIfCmd(ln, kword, true1);
232}
233
234String
235scmdIsDirective(String ln, String kword)
236{
237 return restIfCmd(ln, kword, false((int) 0));
238}
239
240/*
241 * Extract an integer argument.
242 * Non-zero indicates success and is the tail of the string.
243 */
244String
245scmdScanInteger(String s, int *pno)
246{
247 int n;
248
249 while (*s && isspace(*s)((*__ctype_b_loc ())[(int) ((*s))] & (unsigned short int)
_ISspace)
) s++;
250 if (!*s || !isdigit(*s)((*__ctype_b_loc ())[(int) ((*s))] & (unsigned short int)
_ISdigit)
) return 0;
251
252 for (n = 0; *s && isdigit(*s)((*__ctype_b_loc ())[(int) ((*s))] & (unsigned short int)
_ISdigit)
; s++) n = n*10 + *s-'0';
253 *pno = n;
254
255 return s;
256}
257
258/*
259 * Extract a string in quotes.
260 * Non-zero indicates success and is the tail of the string.
261 */
262String
263scmdScanFName(String s, String *pfn)
264{
265 String t;
266
267 while (*s && isspace(*s)((*__ctype_b_loc ())[(int) ((*s))] & (unsigned short int)
_ISspace)
) s++;
268 if (!*s) return 0;
269
270 if (*s != '"') return 0;
271
272 for (t = ++s; *t && *t != '"'; ) t++;
273 *pfn = strnCopy(s, t-s);
274 if (*t) t++;
275 s = t;
276
277 return s;
278}
279
280/*
281 * Extract a word of non-spaces.
282 * Non-zero indicates success and is the tail of the string.
283 */
284String
285scmdScanId(String s, String *pid)
286{
287 String t;
288
289 while (*s && isspace(*s)((*__ctype_b_loc ())[(int) ((*s))] & (unsigned short int)
_ISspace)
) s++;
290 if (!*s) return 0;
291
292 for (t = s; *t && !isspace(*t)((*__ctype_b_loc ())[(int) ((*t))] & (unsigned short int)
_ISspace)
; ) t++;
293 *pid = strnCopy(s, t-s);
294 s = t;
295
296 return s;
297}
298
299/*
300 * Scan the library specifier into an optional tag string and a key string.
301 * Non-zero indicates success and is the tail of the string.
302 *
303 * The arg is either "key" or "id=key" or "id:key".
304 */
305String
306scmdScanLibraryOption(String s, String *pid, String *key)
307{
308 String t;
309
310 /* Scan id, if there. */
311 for (t = s; *t && *t != '=' && *t != ':'; t++) ;
312 if (*t != '=' && *t != ':')
313 *pid = 0;
314 else {
315 if (t == s) return 0;
316 *pid = strnCopy(s, t-s);
317 s = t + 1;
318 }
319
320 /* Scan key. */
321 if (!*s) return 0;
322 for (t = s; *t; t++) ;
323 *key = strCopy(s);
324 s = t;
325
326 return s;
327}
328
329/*****************************************************************************
330 *
331 * :: Specific handlers
332 *
333 ****************************************************************************/
334
335/*
336 * Add filename to the library directory search path.
337 * Return 0 on success, -1 on failure.
338 */
339int
340scmdHandleLibraryDir(String filename)
341{
342 if (!*filename) return -1;
343 fileAddLibraryDirectory(filename);
344 return 0;
345}
346
347/*
348 * Add filename to the include directory search path.
349 * Return 0 on success, -1 on failure.
350 */
351int
352scmdHandleIncludeDir(String filename)
353{
354 if (!*filename) return -1;
355 fileAddIncludeDirectory(filename);
356 return 0;
357}
358
359/*
360 * :: scmdHandleLibrary
361 *
362 * A library reference is a keyed reference if the library file name
363 * has neither directory nor extension.
364 * A keyed reference refers to an archive, which may or may not contain
365 * ao files.
366 *
367 * Add the library to the list to be searched for ao files,
368 * if the library is an archive that contains ao files.
369 * Add a keyed reference to the list to be passed to the loader,
370 * unless the archive contains ao files.
371 * Add a library symbol meaning to the top-level symbol table,
372 * if the id is non-null.
373 * Return 0 on success, -1 on failure.
374 */
375int
376scmdHandleLibrary(String id, String key)
377{
378 Symbol sym;
379 FileName fn;
380 Bool keyed;
381
382 /* Intern the symbol, if present. */
383 sym = id ? symIntern(id)symProbe(id, 1 | 2) : 0;
384
385 /* Determine if the argument is a true file name or a library key. */
386 fn = fnameParseStatic(key);
387 keyed = !(fnameHasDir(fn) || fnameHasType(fn));
388
389 /* If the argument is a library key or an archive of intermed. files,
390 see if we can use it as an archive of intermediate files. */
391 if (keyed || ftypeHas(fn, FTYPENO_AR_INT)) {
392 String fstr;
393 Archive ar;
394
395 if (keyed) {
396 /* Add the key to the loader library key list. */
397 arAddLibraryKey(key);
398
399 fstr = strPrintf("lib%s.%s", key, FTYPE_AR_INT"al");
400 }
401 else
402 fstr = key;
403
404 /* Check for archive not found. */
405 if ((ar = arFrString(fstr)) == 0) {
406 if (!keyed)
407 comsgWarning(NULL((void*)0), ALDOR_F_CantOpen358, fstr);
408 }
409
410 else if (arHasIntermed(ar)((ar)->hasIntermed)) {
411 /* Add the file name to the archive search list. */
412 arAddLibraryFile(fstr);
413
414 /* Define the archive symbol meaning. */
415 if (sym) stabDefArchive(stabFile(), sym, tfType, ar);
416 macexAddMacro(arGetGlobalMacros(ar), false((int) 0));
417 }
418
419 /* Archive of intermediate files not used. */
420 else if (!keyed)
421 comsgWarning(NULL((void*)0), ALDOR_W_CantUseArchive363, fstr);
422 }
423
424 /* If the argument is an intermediate file, use it as a library. */
425 else if (ftypeHas(fn, FTYPENO_INTERMED)) {
426 Lib lib;
427
428 /* Define the library symbol meaning. */
429 if (sym && (lib = libFrString(key)) != 0) {
430 stabDefLibrary(stabFile(), sym, tfType, lib);
431 macexAddMacro(libGetMacros(lib), false((int) 0));
432 }
433 /* Object file not used. */
434 else
435 comsgWarning(NULL((void*)0), ALDOR_W_CantUseObject361, key);
436 }
437
438 /* Unknown file type not used.
439 *
440 * Note that we can't use foo.a, since we can't determine
441 * if a library key even exists that would refer to foo.a,
442 * and foo.a should not contain any intermediate files.
443 */
444 else {
445 comsgWarning(NULL((void*)0), ALDOR_W_CantUseLibrary362, key);
446 return -1;
447 }
448
449 return 0;
450}
451
452int
453scmdHandleMacro(SrcPos pos, String s)
454{
455 SrcLineList lines;
456 TokenList toks;
457
458 lines = listCons(SrcLine)(SrcLine_listPointer->Cons)(slineNew(pos, 5, s), listNil(SrcLine)((SrcLineList) 0));
459 toks = listCons(Token)(Token_listPointer->Cons)(tokKeyword(pos, pos, KW_Macro)tokNew(pos, pos, KW_Macro), scan(lines));
460 /* This should do a bunch more checking... */
461 macexAddMacro(abNormal(parse(&toks), false((int) 0)), true1);
462 return 0;
463}