gwenhywfar  5.10.1
p_dependencies.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Mon Feb 08 2021
3  copyright : (C) 2021 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * Please see toplevel file COPYING for license details *
8  ***************************************************************************/
9 
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13 
14 
17 
18 #include <gwenhywfar/debug.h>
19 #include <gwenhywfar/process.h>
20 #include <gwenhywfar/text.h>
21 #include <gwenhywfar/syncio.h>
22 
23 #include <unistd.h>
24 #include <ctype.h>
25 
26 
27 
28 static int _parseChildNodes(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode);
29 int _parseDep(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode);
30 
31 static int _checkVersion(GWEN_DB_NODE *db,
32  const char *sId,
33  const char *sName,
34  const char *sMinVersion,
35  const char *sMaxVersion);
36 static int _retrieveCflags(GWEN_DB_NODE *db, const char *sId, const char *sName);
37 static int _retrieveLdflags(GWEN_DB_NODE *db, const char *sId, const char *sName);
38 static int _callPkgConfig(GWEN_DB_NODE *db,
39  const char *sId,
40  const char *sName,
41  const char *suffix,
42  const char *args);
43 
44 void _replaceControlCharsWithBlanks(char *ptr);
45 int _retrieveVariables(GWB_CONTEXT *currentContext, GWEN_DB_NODE *db, const char *sId, const char *sName, GWEN_XMLNODE *xmlNode);
46 int _retrieveVariable(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *variableName);
47 
48 
49 
50 
51 
52 
53 int GWB_ParseDependencies(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
54 {
55  int rv;
56 
57  rv=_parseChildNodes(project, currentContext, xmlNode);
58  if (rv<0) {
59  DBG_INFO(NULL, "here (%d)", rv);
60  return rv;
61  }
62 
63  return 0;
64 }
65 
66 
67 
68 int _parseChildNodes(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
69 {
70  GWEN_XMLNODE *n;
71 
72  n=GWEN_XMLNode_GetFirstTag(xmlNode);
73  while (n) {
74  const char *name;
75 
76  name=GWEN_XMLNode_GetData(n);
77  if (name && *name) {
78  int rv;
79 
80  DBG_DEBUG(NULL, "Handling element \"%s\"", name);
81 
82  if (strcasecmp(name, "subdirs")==0)
83  rv=GWB_Parser_ParseSubdirs(project, currentContext, n, _parseChildNodes);
84  else if (strcasecmp(name, "dep")==0)
85  rv=_parseDep(currentContext, n);
86  else
87  rv=GWB_Parser_ParseWellKnownElements(project, currentContext, n, _parseChildNodes);
88  if (rv<0) {
89  DBG_ERROR(GWEN_LOGDOMAIN, "Error in element \"%s\", aborting", name);
90  return rv;
91  }
92  }
93 
95  }
96 
97  return 0;
98 }
99 
100 
101 
102 int _parseDep(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
103 {
104  int rv;
105  const char *s;
106  const char *sId;
107  const char *sName;
108  const char *sMinVersion;
109  const char *sMaxVersion;
110  int required;
111 
112  rv=GWEN_XMLNode_ExpandProperties(xmlNode, GWB_Context_GetVars(currentContext));
113  if (rv<0) {
114  DBG_INFO(NULL, "here (%d)", rv);
115  return rv;
116  }
117 
118  sId=GWEN_XMLNode_GetProperty(xmlNode, "id", NULL);
119  if (!(sId && *sId)) {
120  DBG_ERROR(NULL, "Dependency has no id");
121  return GWEN_ERROR_GENERIC;
122  }
123 
124  sName=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
125  if (!(sName && *sName)) {
126  DBG_ERROR(NULL, "Dependency has no name");
127  return GWEN_ERROR_GENERIC;
128  }
129 
130  s=GWEN_XMLNode_GetProperty(xmlNode, "required", "FALSE");
131  required=(strcasecmp(s, "TRUE")==0)?1:0;
132 
133  sMinVersion=GWEN_XMLNode_GetProperty(xmlNode, "minversion", NULL);
134  sMaxVersion=GWEN_XMLNode_GetProperty(xmlNode, "maxversion", NULL);
135 
136  rv=_checkVersion(GWB_Context_GetVars(currentContext),
137  sId,
138  sName,
139  sMinVersion,
140  sMaxVersion);
141  if (rv==0) {
142  GWEN_XMLNODE *n;
143 
144  rv=_retrieveCflags(GWB_Context_GetVars(currentContext), sId, sName);
145  if (rv<0) {
146  DBG_INFO(NULL, "here (%d)", rv);
147  return rv;
148  }
149  rv=_retrieveLdflags(GWB_Context_GetVars(currentContext), sId, sName);
150  if (rv<0) {
151  DBG_INFO(NULL, "here (%d)", rv);
152  return rv;
153  }
154 
155  n=GWEN_XMLNode_FindFirstTag(xmlNode, "variables", NULL, NULL);
156  if (n) {
157  rv=_retrieveVariables(currentContext, GWB_Context_GetVars(currentContext), sId, sName, n);
158  if (rv<0) {
159  DBG_INFO(NULL, "here (%d)", rv);
160  return rv;
161  }
162  }
163  }
164  else if (rv==GWEN_ERROR_NOT_FOUND) {
165  if (required) {
166  DBG_ERROR(NULL, "Dependency \"%s\" not found but required", sName);
167  return rv;
168  }
169  }
170  else {
171  DBG_INFO(NULL, "here (%d)", rv);
172  return rv;
173  }
174 
175  return 0;
176 }
177 
178 
179 
180 int _retrieveVariables(GWB_CONTEXT *currentContext, GWEN_DB_NODE *db, const char *sId, const char *sName, GWEN_XMLNODE *xmlNode)
181 {
182  GWEN_STRINGLIST *slVariables;
183 
184  slVariables=GWB_Parser_ReadXmlDataIntoStringList(GWB_Context_GetVars(currentContext), xmlNode);
185  if (slVariables) {
187 
188  se=GWEN_StringList_FirstEntry(slVariables);
189  while(se) {
190  const char *s;
191 
193  if (s && *s) {
194  int rv;
195 
196  rv=_retrieveVariable(db, sId, sName, s);
197  if (rv<0) {
198  DBG_ERROR(NULL, "Error retrieving variable \"%s\" for dependency \"%s\"", s, sId);
199  GWEN_StringList_free(slVariables);
200  return rv;
201  }
202  }
204  }
205  }
206 
207  return 0;
208 }
209 
210 
211 
213  const char *sId,
214  const char *sName,
215  const char *sMinVersion,
216  const char *sMaxVersion)
217 {
218  GWEN_BUFFER *argBuffer;
219  GWEN_BUFFER *stdOutBuffer;
220  GWEN_BUFFER *stdErrBuffer;
221  int rv;
222 
223  stdOutBuffer=GWEN_Buffer_new(0, 256, 0, 1);
224  stdErrBuffer=GWEN_Buffer_new(0, 256, 0, 1);
225  argBuffer=GWEN_Buffer_new(0, 256, 0, 1);
226 
227  if (sMinVersion) {
228  GWEN_Buffer_AppendString(argBuffer, " --atleast-version=");
229  GWEN_Buffer_AppendString(argBuffer, sMinVersion);
230  GWEN_Buffer_AppendString(argBuffer, " ");
231  }
232  if (sMaxVersion) {
233  GWEN_Buffer_AppendString(argBuffer, " --max-version=");
234  GWEN_Buffer_AppendString(argBuffer, sMaxVersion);
235  GWEN_Buffer_AppendString(argBuffer, " ");
236  }
237  GWEN_Buffer_AppendString(argBuffer, sName);
238 
239  DBG_DEBUG(NULL, "Running command with args: [%s]", GWEN_Buffer_GetStart(argBuffer));
241  stdOutBuffer, stdErrBuffer);
242  if (rv<0) {
243  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
244  GWEN_Buffer_free(argBuffer);
245  GWEN_Buffer_free(stdErrBuffer);
246  GWEN_Buffer_free(stdOutBuffer);
247  return rv;
248  }
249  GWEN_Buffer_free(argBuffer);
250  GWEN_Buffer_free(stdErrBuffer);
251  GWEN_Buffer_free(stdOutBuffer);
252 
253  GWB_Parser_SetItemValue(db, sId, "_EXISTS", (rv==0)?"TRUE":"FALSE");
254  fprintf(stdout, " dep %s: %s\n", sId, (rv==0)?"found":"not found");
255 
256  return (rv==0)?0:GWEN_ERROR_NOT_FOUND;
257 }
258 
259 
260 
261 int _retrieveCflags(GWEN_DB_NODE *db, const char *sId, const char *sName)
262 {
263  int rv;
264 
265  rv=_callPkgConfig(db, sId, sName, "_CFLAGS", "--cflags");
266  if (rv<0) {
267  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
268  return rv;
269  }
270 
271  return 0;
272 }
273 
274 
275 
276 int _retrieveLdflags(GWEN_DB_NODE *db, const char *sId, const char *sName)
277 {
278  int rv;
279 
280  rv=_callPkgConfig(db, sId, sName, "_LIBS", "--libs");
281  if (rv<0) {
282  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
283  return rv;
284  }
285 
286  return 0;
287 }
288 
289 
290 
291 int _retrieveVariable(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *variableName)
292 {
293  int rv;
294  GWEN_BUFFER *varArgBuffer;
295  GWEN_BUFFER *varSuffixBuffer;
296  const char *s;
297 
298  varArgBuffer=GWEN_Buffer_new(0, 256, 0, 1);
299  GWEN_Buffer_AppendString(varArgBuffer, "--variable=");
300  GWEN_Buffer_AppendString(varArgBuffer, variableName);
301 
302  varSuffixBuffer=GWEN_Buffer_new(0, 256, 0, 1);
303  GWEN_Buffer_AppendString(varSuffixBuffer, "_");
304  s=variableName;
305  while(*s)
306  GWEN_Buffer_AppendByte(varSuffixBuffer, toupper(*(s++)));
307 
308  rv=_callPkgConfig(db, sId, sName, GWEN_Buffer_GetStart(varSuffixBuffer), GWEN_Buffer_GetStart(varArgBuffer));
309  GWEN_Buffer_free(varSuffixBuffer);
310  GWEN_Buffer_free(varArgBuffer);
311  if (rv<0) {
312  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
313  return rv;
314  }
315 
316  return 0;
317 }
318 
319 
320 
322  const char *sId,
323  const char *sName,
324  const char *suffix,
325  const char *args)
326 {
327  GWEN_BUFFER *argBuffer;
328  GWEN_BUFFER *stdOutBuffer;
329  GWEN_BUFFER *stdErrBuffer;
330  int rv;
331 
332  stdOutBuffer=GWEN_Buffer_new(0, 256, 0, 1);
333  stdErrBuffer=GWEN_Buffer_new(0, 256, 0, 1);
334  argBuffer=GWEN_Buffer_new(0, 256, 0, 1);
335 
336  GWEN_Buffer_AppendString(argBuffer, args);
337  GWEN_Buffer_AppendString(argBuffer, " ");
338  GWEN_Buffer_AppendString(argBuffer, sName);
339 
340  DBG_DEBUG(NULL, "Running command with args: [%s]", GWEN_Buffer_GetStart(argBuffer));
341  rv=GWEN_Process_RunCommandWaitAndGather("pkg-config", GWEN_Buffer_GetStart(argBuffer), stdOutBuffer, stdErrBuffer);
342  if (rv<0) {
343  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
344  GWEN_Buffer_free(argBuffer);
345  GWEN_Buffer_free(stdErrBuffer);
346  GWEN_Buffer_free(stdOutBuffer);
347  return rv;
348  }
349  GWEN_Buffer_free(argBuffer);
350 
352  GWEN_Text_CondenseBuffer(stdOutBuffer);
353  GWB_Parser_SetItemValue(db, sId, suffix, GWEN_Buffer_GetStart(stdOutBuffer));
354 
355  GWEN_Buffer_free(stdErrBuffer);
356  GWEN_Buffer_free(stdOutBuffer);
357  return 0;
358 }
359 
360 
361 
363 {
364  while(ptr && *ptr) {
365  if (*ptr<32)
366  *ptr=32;
367  ptr++;
368  }
369 }
370 
371 
372 
int _retrieveVariable(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *variableName)
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition: stringlist.h:53
void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf)
Definition: text.c:1620
struct GWB_CONTEXT GWB_CONTEXT
Definition: context.h:17
GWEN_STRINGLIST * GWB_Parser_ReadXmlDataIntoStringList(GWEN_DB_NODE *db, GWEN_XMLNODE *xmlNode)
Definition: parser.c:283
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
static int _callPkgConfig(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *suffix, const char *args)
const char * GWEN_XMLNode_GetProperty(const GWEN_XMLNODE *n, const char *name, const char *defaultValue)
Definition: xml.c:239
GWENHYWFAR_API int GWEN_Process_RunCommandWaitAndGather(const char *prg, const char *args, GWEN_BUFFER *stdOutBuffer, GWEN_BUFFER *stdErrBuffer)
Definition: process_all.c:31
#define NULL
Definition: binreloc.c:300
static int _retrieveCflags(GWEN_DB_NODE *db, const char *sId, const char *sName)
struct GWB_PROJECT GWB_PROJECT
Definition: project.h:14
#define GWEN_LOGDOMAIN
Definition: logger.h:35
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:390
static int _checkVersion(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *sMinVersion, const char *sMaxVersion)
int GWB_Parser_ParseSubdirs(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode, GWB_PARSER_PARSE_ELEMENT_FN fn)
Definition: parser.c:367
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:406
int GWB_Parser_ParseWellKnownElements(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *n, GWB_PARSER_PARSE_ELEMENT_FN fn)
Definition: parser.c:942
void _replaceControlCharsWithBlanks(char *ptr)
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition: stringlist.c:62
GWEN_XMLNODE * GWEN_XMLNode_FindFirstTag(const GWEN_XMLNODE *n, const char *tname, const char *pname, const char *pvalue)
Definition: xml.c:776
GWEN_DB_NODE * GWB_Context_GetVars(const GWB_CONTEXT *ctx)
Definition: context.c:427
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
GWEN_XMLNODE * GWEN_XMLNode_GetNextTag(const GWEN_XMLNODE *n)
Definition: xml.c:712
int _retrieveVariables(GWB_CONTEXT *currentContext, GWEN_DB_NODE *db, const char *sId, const char *sName, GWEN_XMLNODE *xmlNode)
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition: stringlist.h:56
static int _parseChildNodes(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
#define GWEN_ERROR_GENERIC
Definition: error.h:62
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:394
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
int GWB_ParseDependencies(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
GWEN_XMLNODE * GWEN_XMLNode_GetFirstTag(const GWEN_XMLNODE *n)
Definition: xml.c:705
const char * GWEN_XMLNode_GetData(const GWEN_XMLNODE *n)
Definition: xml.c:370
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:398
#define GWEN_ERROR_NOT_FOUND
Definition: error.h:89
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
void GWB_Parser_SetItemValue(GWEN_DB_NODE *db, const char *sId, const char *suffix, const char *value)
Definition: parser.c:856
int _parseDep(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
int GWEN_XMLNode_ExpandProperties(const GWEN_XMLNODE *n, GWEN_DB_NODE *dbVars)
Definition: xml.c:634
struct GWEN__XMLNODE GWEN_XMLNODE
Definition: xml.h:156
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989
static int _retrieveLdflags(GWEN_DB_NODE *db, const char *sId, const char *sName)