Coding style cleanup
[platform/kernel/u-boot.git] / board / MAI / bios_emulator / scitech / src / pm / common.c
1 /****************************************************************************
2 *
3 *                   SciTech OS Portability Manager Library
4 *
5 *  ========================================================================
6 *
7 *    The contents of this file are subject to the SciTech MGL Public
8 *    License Version 1.0 (the "License"); you may not use this file
9 *    except in compliance with the License. You may obtain a copy of
10 *    the License at http://www.scitechsoft.com/mgl-license.txt
11 *
12 *    Software distributed under the License is distributed on an
13 *    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 *    implied. See the License for the specific language governing
15 *    rights and limitations under the License.
16 *
17 *    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18 *
19 *    The Initial Developer of the Original Code is SciTech Software, Inc.
20 *    All Rights Reserved.
21 *
22 *  ========================================================================
23 *
24 * Language:     ANSI C
25 * Environment:  Any
26 *
27 * Description:  Module containing code common to all platforms.
28 *
29 ****************************************************************************/
30
31 #include "pmapi.h"
32 #include "drvlib/os/os.h"
33 #if defined(__WIN32_VXD__) || defined(__OS2_VDD__) || defined(__NT_DRIVER__)
34 #include "sdd/sddhelp.h"
35 #else
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #endif
40
41 /*---------------------------- Global variables ---------------------------*/
42
43 /* {secret} */
44 long _VARAPI    ___drv_os_type = _OS_UNSUPPORTED;
45 static char     localBPDPath[PM_MAX_PATH] = "";
46
47 /*----------------------------- Implementation ----------------------------*/
48
49 /****************************************************************************
50 PARAMETERS:
51 path    - Local path to the Nucleus BPD driver files.
52
53 REMARKS:
54 This function is used by the application program to override the location
55 of the Nucleus driver files that are loaded. Normally the loader code
56 will look in the system Nucleus directories first, then in the 'drivers'
57 directory relative to the current working directory, and finally relative
58 to the MGL_ROOT environment variable. By default the local BPD path is
59 always set to the current directory if not initialised.
60 ****************************************************************************/
61 void PMAPI PM_setLocalBPDPath(
62     const char *path)
63 {
64     PM_init();
65     strncpy(localBPDPath,path,sizeof(localBPDPath));
66     localBPDPath[sizeof(localBPDPath)-1] = 0;
67 }
68
69 /****************************************************************************
70 PARAMETERS:
71 bpdpath     - Place to store the actual path to the file
72 cachedpath  - Place to store the cached BPD driver path
73 trypath     - Path to try to find the BPD file in
74 subpath     - Optional sub path to append to trypath
75 dllname     - Name of the Binary Portable DLL to load
76
77 RETURNS:
78 True if found, false if not.
79
80 REMARKS:
81 Trys the specified path to see if the BPD file can be found or not. If so,
82 the path used is returned in bpdpath and cachedpath.
83 ****************************************************************************/
84 static ibool TryPath(
85     char *bpdpath,
86     char *cachedpath,
87     const char *trypath,
88     const char *subpath,
89     const char *dllname)
90 {
91     char    filename[256];
92     FILE    *f;
93
94     strcpy(bpdpath, trypath);
95     PM_backslash(bpdpath);
96     strcat(bpdpath,subpath);
97     PM_backslash(bpdpath);
98     strcpy(filename,bpdpath);
99     strcat(filename,dllname);
100     if ((f = fopen(filename,"rb")) == NULL)
101         return false;
102     if (cachedpath)
103         strcpy(cachedpath,bpdpath);
104     fclose(f);
105     return true;
106 }
107
108 /****************************************************************************
109 RETURNS:
110 True if local override enabled, false if not.
111
112 REMARKS:
113 Tests to see if the local override option is enabled, and if so it will
114 look for the Nucleus drivers in the local application directories in
115 preference to the Nucleus system directories.
116 ****************************************************************************/
117 static ibool GetLocalOverride(void)
118 {
119     char            filename[256];
120     FILE            *f;
121     static ibool    local_override = -1;
122
123     if (local_override == -1) {
124         local_override = false;
125         strcpy(filename,PM_getNucleusPath());
126         PM_backslash(filename);
127         strcat(filename,"graphics.ini");
128         if ((f = fopen(filename,"r")) != NULL) {
129             while (!feof(f) && fgets(filename,sizeof(filename),f)) {
130                 if (strnicmp(filename,"uselocal",8) == 0) {
131                     local_override = ((*(filename+9) - '0') == 1);
132                     break;
133                     }
134                 }
135             fclose(f);
136             }
137         }
138     return local_override;
139 }
140
141 /****************************************************************************
142 DESCRIPTION:
143 Sets the location of the debug log file.
144
145 HEADER:
146 pmapi.h
147
148 PARAMETERS:
149 dllname - Name of the Binary Portable DLL to load
150 bpdpath - Place to store the actual path to the file
151
152 RETURNS:
153 True if found, false if not.
154
155 REMARKS:
156 Finds the location of a specific Binary Portable DLL, by searching all
157 the standard SciTech Nucleus driver locations.
158 ****************************************************************************/
159 ibool PMAPI PM_findBPD(
160     const char *dllname,
161     char *bpdpath)
162 {
163     static char cachedpath[PM_MAX_PATH] = "";
164
165     /* On the first call determine the path to the Nucleus drivers */
166     if (cachedpath[0] == 0) {
167         /* First try in the global system Nucleus driver path if
168          * the local override setting is not enabled.
169          */
170         PM_init();
171         if (!GetLocalOverride()) {
172             if (TryPath(bpdpath,cachedpath,PM_getNucleusPath(),"",dllname))
173                 return true;
174             }
175
176         /* Next try in the local application directory if available */
177         if (localBPDPath[0] != 0) {
178             if (TryPath(bpdpath,cachedpath,localBPDPath,"",dllname))
179                 return true;
180             }
181         else {
182 #if !defined(__WIN32_VXD__) && !defined(__NT_DRIVER__)
183             char    *mgl_root;
184             if ((mgl_root = getenv("MGL_ROOT")) != NULL) {
185                 if (TryPath(bpdpath,cachedpath,mgl_root,"drivers",dllname))
186                     return true;
187                 }
188 #endif
189             PM_getCurrentPath(bpdpath,PM_MAX_PATH);
190             if (TryPath(bpdpath,cachedpath,bpdpath,"drivers",dllname))
191                 return true;
192             }
193
194         /* Finally try in the global system path again so that we
195          * will still find the drivers in the global system path if
196          * the local override option is on, but the application does
197          * not have any local override drivers.
198          */
199         if (TryPath(bpdpath,cachedpath,PM_getNucleusPath(),"",dllname))
200             return true;
201
202         /* Whoops, we can't find the BPD file! */
203         return false;
204         }
205
206     /* Always try in the previously discovered path */
207     return TryPath(bpdpath,NULL,cachedpath,"",dllname);
208 }
209
210 /****************************************************************************
211 REMARKS:
212 Copies a string into another, and returns dest + strlen(src).
213 ****************************************************************************/
214 static char *_stpcpy(
215     char *_dest,
216     const char *_src)
217 {
218     if (!_dest || !_src)
219         return 0;
220     while ((*_dest++ = *_src++) != 0)
221         ;
222     return --_dest;
223 }
224
225 /****************************************************************************
226 REMARKS:
227 Copies a string into another, stopping at the maximum length. The string
228 is properly terminated (unlike strncpy).
229 ****************************************************************************/
230 static void safe_strncpy(
231     char *dst,
232     const char *src,
233     unsigned maxlen)
234 {
235     if (dst) {
236         if(strlen(src) >= maxlen) {
237             strncpy(dst, src, maxlen);
238             dst[maxlen] = 0;
239             }
240         else
241             strcpy(dst, src);
242         }
243 }
244
245 /****************************************************************************
246 REMARKS:
247 Determins if the dot separator is present in the string.
248 ****************************************************************************/
249 static int findDot(
250     char *p)
251 {
252     if (*(p-1) == '.')
253         p--;
254     switch (*--p) {
255         case ':':
256             if (*(p-2) != '\0')
257                 break;
258         case '/':
259         case '\\':
260         case '\0':
261             return true;
262         }
263     return false;
264 }
265
266 /****************************************************************************
267 DESCRIPTION:
268 Make a full pathname from split components.
269
270 HEADER:
271 pmapi.h
272
273 PARAMETERS:
274 path    - Place to store full path
275 drive   - Drive component for path
276 dir     - Directory component for path
277 name    - Filename component for path
278 ext     - Extension component for path
279
280 REMARKS:
281 Function to make a full pathname from split components. Under Unix the
282 drive component will usually be empty. If the drive, dir, name, or ext
283 parameters are null or empty, they are not inserted in the path string.
284 Otherwise, if the drive doesn't end with a colon, one is inserted in the
285 path. If the dir doesn't end in a slash, one is inserted in the path.
286 If the ext doesn't start with a dot, one is inserted in the path.
287
288 The maximum sizes for the path string is given by the constant PM_MAX_PATH,
289 which includes space for the null-terminator.
290
291 SEE ALSO:
292 PM_splitPath
293 ****************************************************************************/
294 void PMAPI PM_makepath(
295     char *path,
296     const char *drive,
297     const char *dir,
298     const char *name,
299     const char *ext)
300 {
301     if (drive && *drive) {
302         *path++ = *drive;
303         *path++ = ':';
304         }
305     if (dir && *dir) {
306         path = _stpcpy(path,dir);
307         if (*(path-1) != '\\' && *(path-1) != '/')
308 #ifdef  __UNIX__
309             *path++ = '/';
310 #else
311             *path++ = '\\';
312 #endif
313         }
314     if (name)
315         path = _stpcpy(path,name);
316     if (ext && *ext) {
317         if (*ext != '.')
318             *path++ = '.';
319         path = _stpcpy(path,ext);
320         }
321     *path = 0;
322 }
323
324 /****************************************************************************
325 DESCRIPTION:
326 Split a full pathname into components.
327
328 HEADER:
329 pmapi.h
330
331 PARAMETERS:
332 path    - Full path to split
333 drive   - Drive component for path
334 dir     - Directory component for path
335 name    - Filename component for path
336 ext     - Extension component for path
337
338 RETURNS:
339 Flags indicating what components were parsed.
340
341 REMARKS:
342 Function to split a full pathmame into separate components in the form
343
344     X:\DIR\SUBDIR\NAME.EXT
345
346 and splits path into its four components. It then stores those components
347 in the strings pointed to by drive, dir, name and ext. (Each component is
348 required but can be a NULL, which means the corresponding component will be
349 parsed but not stored).
350
351 The maximum sizes for these strings are given by the constants PM_MAX_DRIVE
352 and PM_MAX_PATH. PM_MAX_DRIVE is always 4, and PM_MAX_PATH is usually at
353 least 256 characters. Under Unix the dir, name and ext components may be
354 up to the full path in length.
355
356 SEE ALSO:
357 PM_makePath
358 ****************************************************************************/
359 int PMAPI PM_splitpath(
360     const char *path,
361     char *drive,
362     char *dir,
363     char *name,
364     char *ext)
365 {
366     char    *p;
367     int     temp,ret;
368     char    buf[PM_MAX_PATH+2];
369
370     /* Set all string to default value zero */
371     ret = 0;
372     if (drive)  *drive = 0;
373     if (dir)    *dir = 0;
374     if (name)   *name = 0;
375     if (ext)    *ext = 0;
376
377     /* Copy filename into template up to PM_MAX_PATH characters */
378     p = buf;
379     if ((temp = strlen(path)) > PM_MAX_PATH)
380         temp = PM_MAX_PATH;
381     *p++ = 0;
382     strncpy(p, path, temp);
383     *(p += temp) = 0;
384
385     /* Split the filename and fill corresponding nonzero pointers */
386     temp = 0;
387     for (;;) {
388         switch (*--p) {
389             case '.':
390                 if (!temp && (*(p+1) == '\0'))
391                     temp = findDot(p);
392                 if ((!temp) && ((ret & PM_HAS_EXTENSION) == 0)) {
393                     ret |= PM_HAS_EXTENSION;
394                     safe_strncpy(ext, p, PM_MAX_PATH - 1);
395                     *p = 0;
396                     }
397                 continue;
398             case ':':
399                 if (p != &buf[2])
400                     continue;
401             case '\0':
402                 if (temp) {
403                     if (*++p)
404                         ret |= PM_HAS_DIRECTORY;
405                     safe_strncpy(dir, p, PM_MAX_PATH - 1);
406                     *p-- = 0;
407                     break;
408                     }
409             case '/':
410             case '\\':
411                 if (!temp) {
412                     temp++;
413                     if (*++p)
414                         ret |= PM_HAS_FILENAME;
415                     safe_strncpy(name, p, PM_MAX_PATH - 1);
416                     *p-- = 0;
417                     if (*p == 0 || (*p == ':' && p == &buf[2]))
418                         break;
419                     }
420                 continue;
421             case '*':
422             case '?':
423                 if (!temp)
424                     ret |= PM_HAS_WILDCARDS;
425             default:
426                 continue;
427             }
428         break;
429         }
430     if (*p == ':') {
431         if (buf[1])
432             ret |= PM_HAS_DRIVE;
433         safe_strncpy(drive, &buf[1], PM_MAX_DRIVE - 1);
434         }
435     return ret;
436 }
437
438 /****************************************************************************
439 DESCRIPTION:
440 Block until a specific time has elapsed since the last call
441
442 HEADER:
443 pmapi.h
444
445 PARAMETERS:
446 milliseconds    - Number of milliseconds for delay
447
448 REMARKS:
449 This function will block the calling thread or process until the specified
450 number of milliseconds have passed since the /last/ call to this function.
451 The first time this function is called, it will return immediately. On
452 subsquent calls it will block until the specified time has elapsed, or it
453 will return immediately if the time has already elapsed.
454
455 This function is useful to provide constant time functionality in a
456 program, such as a frame rate limiter for graphics applications etc.
457
458 SEE ALSO:
459 PM_sleep
460 ****************************************************************************/
461 void PMAPI PM_blockUntilTimeout(
462     ulong milliseconds)
463 {
464     ulong                   microseconds = milliseconds * 1000L,msDelay;
465     static LZTimerObject    tm;
466     static ibool            firstTime = true;
467
468     if (firstTime) {
469         firstTime = false;
470         LZTimerOnExt(&tm);
471         }
472     else {
473         if ((msDelay = (microseconds - LZTimerLapExt(&tm)) / 1000L) > 0)
474             PM_sleep(msDelay);
475         while (LZTimerLapExt(&tm) < microseconds)
476             ;
477         LZTimerOffExt(&tm);
478         LZTimerOnExt(&tm);
479         }
480 }