1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 /****************************************************************************/
4 /* */
5 /* File: misc.c */
6 /* */
7 /* Purpose: miscellaneous routines */
8 /* */
9 /* Author: Klaus Johannsen */
10 /* Institut fuer Computeranwendungen */
11 /* Universitaet Stuttgart */
12 /* Pfaffenwaldring 27 */
13 /* 70569 Stuttgart */
14 /* internet: ug@ica3.uni-stuttgart.de */
15 /* */
16 /* History: 08.12.94 begin, ug3-version */
17 /* */
18 /* Revision: 07.09.95 */
19 /* */
20 /****************************************************************************/
21
22 /****************************************************************************/
23 /* */
24 /* include files */
25 /* system include files */
26 /* application include files */
27 /* */
28 /****************************************************************************/
29
30 #include <config.h>
31 #include <cmath>
32 #include <cassert>
33 #include <cstdlib>
34 #include <cstring>
35 #include <ctype.h>
36 #include <cstddef>
37 #include <cstdio>
38 #include <climits>
39 #include <float.h>
40
41 #include "ugtypes.h"
42 #include "architecture.h"
43 #include "misc.h"
44 #include "heaps.h"
45
46 USING_UG_NAMESPACE
47
48 /****************************************************************************/
49 /* */
50 /* defines in the following order */
51 /* */
52 /* compile time constants defining static data size (i.e. arrays) */
53 /* other constants */
54 /* macros */
55 /* */
56 /****************************************************************************/
57
58 /****************************************************************************/
59 /* */
60 /* data structures used in this source file (exported data structures are */
61 /* in the corresponding include file!) */
62 /* */
63 /****************************************************************************/
64
65
66
67 /****************************************************************************/
68 /* */
69 /* definition of exported global variables */
70 /* */
71 /****************************************************************************/
72
73 #ifndef ModelP
74 int PPIF::me = 0; /* to have in the serial case this variable as a dummy */
75 int PPIF::master = 0; /* to have in the serial case this variable as a dummy */
76 int PPIF::procs = 1; /* to have in the serial case this variable as a dummy */
77 int NS_PREFIX _proclist_ = -1; /* to have in the serial case this variable as a dummy */
78 int NS_PREFIX _partition_ = 0; /* to have in the serial case this variable as a dummy */
79 #endif
80
81 /****************************************************************************/
82 /* */
83 /* definition of variables global to this source file only (static!) */
84 /* */
85 /****************************************************************************/
86
87
88 /****************************************************************************/
89 /* */
90 /* forward declarations of macros */
91 /* */
92 /****************************************************************************/
93
94 #define MIN_DETERMINANT 1e-8
95
96 /* for ExpandCShellVars */
97 #define CSHELL_VAR_BEGIN "$("
98 #define CSHELL_VAR_BEGIN_LEN 2 /* strlen(CSHELL_VAR_BEGIN) */
99 #define CSHELL_VAR_END ")"
100 #define CSHELL_VAR_END_LEN 1 /* strlen(CSHELL_VAR_END) */
101
102 /****************************************************************************/
103 /****************************************************************************/
104 /****************************************************************************/
105 /**** ****/
106 /**** general routines ****/
107 /**** ****/
108 /****************************************************************************/
109 /****************************************************************************/
110 /****************************************************************************/
111
112 /****************************************************************************/
113 /** \brief Transform an INT into a bitpattern string
114
115 \param n - integer to convert
116 \param text - string of size >= 33 for conversion
117
118 This function transforms an INT into a bitpattern string consisting of 0s
119 and 1s only.
120 */
121 /****************************************************************************/
122
INT_2_bitpattern(INT n,char text[33])123 void NS_PREFIX INT_2_bitpattern (INT n, char text[33])
124 {
125 INT i;
126
127 memset(text,'0',32*sizeof(char));
128
129 for (i=0; i<32; i++)
130 if ((1<<i)&n)
131 text[31-i] = '1';
132 text[32] = '\0';
133
134 return;
135 }
136
137 /****************************************************************************/
138 /** \brief Compose a headline of chars with string centered
139
140 \param str - string to print to
141 \param PatLen - width of headline
142 \param text - text to center in headline
143 \param p - char replicated for headline
144 \param end - trailing string (optional)
145
146 Fill str up to PatLen with pattern and center text in it. Terminate the str with end
147
148 \return
149 0 okay 1 error
150 */
151 /****************************************************************************/
152
CenterInPattern(char * str,INT PatLen,const char * text,char p,const char * end)153 INT NS_PREFIX CenterInPattern (char *str, INT PatLen, const char *text, char p, const char *end)
154 {
155 INT i,TextBegin,TextEnd,TextLen;
156
157 TextLen = strlen(text);
158 TextBegin = (PatLen-TextLen)/2;
159 TextEnd = TextBegin+TextLen;
160
161 if (TextLen>PatLen)
162 return (CenterInPattern(str,PatLen," text too long ",p,end));
163
164 for (i=0; i<TextBegin-1; i++)
165 str[i] = p;
166 str[i] = ' ';
167 for (i=TextBegin; i<TextEnd; i++)
168 str[i] = *(text++);
169 str[i++] = ' ';
170 for (; i<PatLen; i++)
171 str[i] = p;
172 str[PatLen] = '\0';
173 if (end!=NULL)
174 strcat(str,end);
175
176 return (0);
177 }
178
179 #define FMTBUFFSIZE 1031
180
181 static char newfmt[FMTBUFFSIZE];
182
183 /****************************************************************************/
184 /** \brief Expand (make explicit) charset-ranges in scanf
185
186 This function expands (make explicit) charset-ranges in scanf.
187 For example '%<number>[...a-d...]' --> '%<number>[...abcd...]'.
188
189 \return
190 .n new pointer to char
191 */
192 /****************************************************************************/
expandfmt(const char * fmt)193 char * NS_PREFIX expandfmt (const char *fmt)
194 {
195 const char *pos;
196 char *newpos;
197 char leftchar,rightchar;
198 int newlen;
199
200 /* calculate min size of newfmt */
201 newlen = strlen(fmt);
202 assert (newlen<FMTBUFFSIZE-1);
203
204 pos = fmt;
205 newpos = newfmt;
206
207 /* scan fmt for %<number>[ */
208 while (*pos!='\0')
209 {
210 /* copy til '%' */
211 while (*pos!='%' && *pos!='\0')
212 *(newpos++) = *(pos++);
213
214 if (*pos=='\0')
215 break;
216
217 *(newpos++) = *(pos++);
218
219 /* copy til !isdigit */
220 while (isdigit(*pos) && *pos!='\0')
221 *(newpos++) = *(pos++);
222
223 if (*pos=='\0')
224 break;
225
226 if (*pos!='[')
227 continue;
228
229 *(newpos++) = *(pos++);
230
231 /* ']' following '[' is included in the charset */
232 if ((*pos)==']')
233 *(newpos++) = *(pos++);
234
235 /* '^]' following '[' is included in the charset */
236 else if ((*pos)=='^' && (*(pos+1))==']')
237 {
238 *(newpos++) = *(pos++);
239 *(newpos++) = *(pos++);
240 }
241
242 while (*pos!=']' && *pos!='\0')
243 {
244 /* now we are inside the charset '[...]': */
245
246 /* treat character ranges indicated by '-' */
247 while (*pos!='-' && *pos!=']' && *pos!='\0')
248 *(newpos++) = *(pos++);
249
250 if (*pos=='\0')
251 break;
252
253 if ((*pos)==']')
254 continue;
255
256 /* gotya: is left char < right char? */
257 leftchar = *(pos-1);
258 rightchar = *(pos+1);
259
260 if (leftchar=='[' || rightchar==']')
261 {
262 *(newpos++) = *(pos++);
263 continue;
264 }
265
266 if (leftchar>=rightchar)
267 {
268 *(newpos++) = *(pos++);
269 continue;
270 }
271
272 if (leftchar+1==rightchar)
273 {
274 /* for example '...b-c...' */
275 pos++;
276 continue;
277 }
278
279 /* calc new size and expand range */
280 newlen += rightchar-leftchar-2;
281 assert (newlen<FMTBUFFSIZE-1);
282
283 leftchar++;
284 pos++;
285
286 while (leftchar<rightchar)
287 {
288 if (leftchar=='^' || leftchar==']')
289 {
290 leftchar++;
291 continue;
292 }
293 *(newpos++) = leftchar++;
294 }
295 }
296 }
297
298 *newpos = '\0';
299
300 return (newfmt);
301 }
302
ExpandCShellVars(char * string)303 char * NS_PREFIX ExpandCShellVars (char *string)
304 {
305 if (strstr(string,CSHELL_VAR_BEGIN)!=NULL)
306 {
307 /* shell var reference contained: copy string and expand vars */
308 char *copy = strdup(string);
309 char *p0 = copy; /* current pos */
310 char *p1; /* end of token */
311
312 string[0] = '\0';
313
314 while ((p1 = strstr(p0,CSHELL_VAR_BEGIN))!=NULL)
315 {
316 char *var;
317
318 /* enclose current pos (p0) to CSHELL_VAR_BEGIN between p0,p1 */
319 *p1 = '\0';
320
321 /* copy verbatim */
322 strcat(string,p0);
323
324 /* advance p0 to begin of shell var name */
325 p0 = p1+CSHELL_VAR_BEGIN_LEN;
326
327 /* enclose current pos (p0) to CSHELL_VAR_END between p0,p1 */
328 p1 = strstr(p0,CSHELL_VAR_END);
329 if (p1==NULL)
330 {
331 free(copy);
332 return NULL;
333 }
334 *p1 = '\0';
335
336 /* copy shell variable iff */
337 var = getenv(p0);
338 if (var==NULL)
339 {
340 free(copy);
341 return NULL;
342 }
343 strcat(string,var);
344
345 /* advance p0 */
346 p0 = p1+CSHELL_VAR_END_LEN;
347 }
348 /* copy remainder */
349 strcat(string,p0);
350 free(copy);
351 }
352 return string;
353 }
354
355 /****************************************************************************/
356 /** \brief Split a string into tokens each of maximal length 'n+1'
357
358 \param str - pointer to char (const)
359 \param sep - pointer to char (const)
360 \param n - integer, number of chars in token
361 \param token - pointer to char
362
363 This function splits a string into tokens each of maximal length 'n+1'.
364 A pointer to the next char following the token (its a sep) is returned.
365 NB: possibly check whether the returned char is a sep.
366 If not: the token was to long and only the first n chars where copied!
367
368 \return
369 .n pointer to token
370 .n NULL if token larger than n.
371 */
372 /****************************************************************************/
373
strntok(const char * str,const char * sep,int n,char * token)374 const char * NS_PREFIX strntok (const char *str, const char *sep, int n, char *token)
375 {
376 int i;
377
378 /* scan while current char is a seperator */
379 while ((*str!='\0') && (strchr(sep,*str)!=NULL)) str++;
380
381 /* copy into token */
382 for (i=0; i<n; i++,str++)
383 if ((*str!='\0') && (strchr(sep,*str)==NULL))
384 token[i] = *str;
385 else
386 break;
387
388 if (strchr(sep,*str)==NULL)
389 return (NULL); /* ERROR: token too long! */
390
391 /* 0-terminate string */
392 token[i] = '\0';
393
394 return (str);
395 }
396
397 /****************************************************************************/
398 /** \brief Convert a (memory)size specification from String to MEM (long int)
399
400 \param s - input string
401 \param mem_size - the specified mem size in byte
402
403 This function converts a (memory)size specification from String to type MEM (an integer type).
404 The size specification contains an integer number followed by an optional unit specifier:
405 G for gigabyte
406 M for megabyte
407 K for kilobyte
408 (also the lower case chars are recognized).
409
410 EXAMPLE:
411 "10M" is converted to 10485760 (10 mega byte).
412
413 \return
414 INT: 0 ok
415 1 integer could not be read
416 2 invalid unit specifier
417
418 \sa
419 MEM, WriteMemSizeToString
420 */
421 /****************************************************************************/
422
ReadMemSizeFromString(const char * s,MEM * mem_size)423 INT NS_PREFIX ReadMemSizeFromString (const char *s, MEM *mem_size )
424 {
425 float mem;
426
427 if (sscanf( s, "%e",&mem)!=1)
428 return(1);
429
430 switch( s[strlen(s)-1] )
431 {
432 case 'k' : case 'K' : /* check for [kK]ilobyte-notation */
433 *mem_size = (MEM)floor(mem * KBYTE);
434 return(0);
435 case 'm' : case 'M' : /* check for [mM]egabyte-notation */
436 *mem_size = (MEM)floor(mem * MBYTE);
437 return(0);
438 case 'g' : case 'G' : /* check for [gG]igabyte-notation */
439 *mem_size = (MEM)floor(mem * GBYTE);
440 return(0);
441 case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : /* no mem unit character recognized */
442 *mem_size = (MEM)floor(mem);
443 return(0);
444 default : /* unknown mem unit character */
445 return(2);
446 }
447 }
448
449 /****************************************************************************/
450 /** \brief Convert a (memory)size MEM to string
451
452 \param s - input string
453 \param mem_size - the specified mem size in byte
454
455 This function writes a MEM size in MBytes to string in a format that is recognized by
456 WriteMemSizeToString.
457
458 \return
459 0 ok
460
461 \sa
462 MEM, ReadMemSizeFromString
463 */
464 /****************************************************************************/
465
WriteMemSizeToString(MEM mem_size,char * s)466 INT NS_PREFIX WriteMemSizeToString (MEM mem_size, char *s)
467 {
468 float mem = mem_size;
469
470 /* write mem size in units of MByte */
471 sprintf(s, "%g M",mem/MBYTE);
472 return 0;
473 }
474