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