1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1996, 2005 - 3D Realms Entertainment
4 
5 This file is NOT part of Shadow Warrior version 1.2
6 However, it is either an older version of a file that is, or is
7 some test code written during the development of Shadow Warrior.
8 This file is provided purely for educational interest.
9 
10 Shadow Warrior is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24 
25 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
26 */
27 //-------------------------------------------------------------------------
28 
29 // scriplib.c
30 #include "build.h"
31 #include "editor.h"
32 #include "cache1d.h"
33 
34 #include "names2.h"
35 #include "game.h"
36 
37 #include "parse.h"
38 
39 #define PATHSEPERATOR   '\\'
40 
41 
42 //#define COMPUTE_TOTALS	1
43 
44 /*
45 =============================================================================
46 
47                         ABNORMAL TERMINATION
48 
49 =============================================================================
50 */
Error(const char * error,...)51 void Error(const char *error, ...)
52 {
53     va_list argptr;
54 
55     va_start(argptr,error);
56     vprintf(error,argptr);
57     va_end(argptr);
58     printf("\n");
59     exit(1);
60 }
61 
62 
63 
64 /*
65 =============================================================================
66 
67                         PARSING STUFF
68 
69 =============================================================================
70 */
71 
72 char    token[MAXTOKEN];
73 char    *scriptbuffer,*script_p,*scriptend_p;
74 int     grabbed;
75 int     scriptline;
76 SWBOOL    endofscript;
77 SWBOOL    tokenready;                     // only TRUE if UnGetToken was just called
78 
79 /*
80 ==============
81 =
82 = LoadScriptFile
83 =
84 ==============
85 */
86 
LoadScriptFile(const char * filename)87 SWBOOL LoadScriptFile(const char *filename)
88 {
89     int size, readsize;
90     int fp;
91 
92 
93     if ((fp=kopen4load(filename,0)) == -1)
94     {
95         // If there's no script file, forget it.
96         return FALSE;
97     }
98 
99     size = kfilelength(fp);
100 
101     scriptbuffer = (char *)Xmalloc(size);
102 
103     ASSERT(scriptbuffer != NULL);
104 
105     readsize = kread(fp, scriptbuffer, size);
106 
107     kclose(fp);
108 
109     ASSERT(readsize == size);
110 
111 
112     // Convert filebuffer to all upper case
113     //Bstrupr(scriptbuffer);
114 
115     script_p = scriptbuffer;
116     scriptend_p = script_p + size;
117     scriptline = 1;
118     endofscript = FALSE;
119     tokenready = FALSE;
120     return TRUE;
121 }
122 
123 
124 /*
125 ==============
126 =
127 = UnGetToken
128 =
129 = Signals that the current token was not used, and should be reported
130 = for the next GetToken.  Note that
131 
132 GetToken (TRUE);
133 UnGetToken ();
134 GetToken (FALSE);
135 
136 = could cross a line boundary.
137 =
138 ==============
139 */
140 
UnGetToken(void)141 void UnGetToken(void)
142 {
143     tokenready = TRUE;
144 }
145 
146 
147 /*
148 ==============
149 =
150 = GetToken
151 =
152 ==============
153 */
154 
GetToken(SWBOOL crossline)155 void GetToken(SWBOOL crossline)
156 {
157     char    *token_p;
158 
159     if (tokenready)                         // is a token already waiting?
160     {
161         tokenready = FALSE;
162         return;
163     }
164 
165     if (script_p >= scriptend_p)
166     {
167         if (!crossline)
168             Error("Line %i is incomplete\n",scriptline);
169         endofscript = TRUE;
170         return;
171     }
172 
173 //
174 // skip space
175 //
176 skipspace:
177     while (*script_p <= 32)
178     {
179         if (script_p >= scriptend_p)
180         {
181             if (!crossline)
182                 Error("Line %i is incomplete\n",scriptline);
183             endofscript = TRUE;
184             return;
185         }
186         if (*script_p++ == '\n')
187         {
188             if (!crossline)
189                 Error("Line %i is incomplete\n",scriptline);
190             scriptline++;
191         }
192     }
193 
194     if (script_p >= scriptend_p)
195     {
196         if (!crossline)
197             Error("Line %i is incomplete\n",scriptline);
198         endofscript = TRUE;
199         return;
200     }
201 
202     if (*script_p == '#')   // # is comment field
203     {
204         if (!crossline)
205             Error("Line %i is incomplete\n",scriptline);
206         while (*script_p++ != '\n')
207             if (script_p >= scriptend_p)
208             {
209                 endofscript = TRUE;
210                 return;
211             }
212         goto skipspace;
213     }
214 
215 //
216 // copy token
217 //
218     token_p = token;
219 
220     while (*script_p > 32 && *script_p != '#')
221     {
222         *token_p++ = *script_p++;
223         if (script_p == scriptend_p)
224             break;
225         ASSERT(token_p != &token[MAXTOKEN]);
226 //			Error ("Token too large on line %i\n",scriptline);
227     }
228 
229     *token_p = 0;
230 }
231 
232 
233 /*
234 ==============
235 =
236 = TokenAvailable
237 =
238 = Returns true if there is another token on the line
239 =
240 ==============
241 */
242 
TokenAvailable(void)243 SWBOOL TokenAvailable(void)
244 {
245     char    *search_p;
246 
247     search_p = script_p;
248 
249     if (search_p >= scriptend_p)
250         return FALSE;
251 
252     while (*search_p <= 32)
253     {
254         if (*search_p == '\n')
255             return FALSE;
256         search_p++;
257         if (search_p == scriptend_p)
258             return FALSE;
259 
260     }
261 
262     if (*search_p == '#')
263         return FALSE;
264 
265     return TRUE;
266 }
267 
DefaultExtension(char * path,char * extension)268 void DefaultExtension(char *path, char *extension)
269 {
270     char    *src;
271 //
272 // if path doesn't have a .EXT, append extension
273 // (extension should include the .)
274 //
275     src = path + strlen(path) - 1;
276 
277     while (*src != '\\' && src != path)
278     {
279         if (*src == '.')
280             return;                 // it has an extension
281         src--;
282     }
283 
284     strcat(path, extension);
285 }
286 
287 
DefaultPath(char * path,char * basepath)288 void DefaultPath(char *path, char *basepath)
289 {
290     char    temp[128];
291 
292     if (path[0] == '\\')
293         return;                                                 // absolute path location
294     strcpy(temp,path);
295     strcpy(path,basepath);
296     strcat(path,temp);
297 }
298 
299 
StripFilename(char * path)300 void    StripFilename(char *path)
301 {
302     int             length;
303 
304     length = strlen(path)-1;
305     while (length > 0 && path[length] != PATHSEPERATOR)
306         length--;
307     path[length] = 0;
308 }
309 
310 
ExtractFileBase(char * path,char * dest)311 void ExtractFileBase(char *path, char *dest)
312 {
313     char    *src;
314     int             length;
315 
316     src = path + strlen(path) - 1;
317 
318 //
319 // back up until a \ or the start
320 //
321     while (src != path && *(src-1) != '\\')
322         src--;
323 
324 //
325 // copy up to eight characters
326 //
327     memset(dest,0,8);
328     length = 0;
329     while (*src && *src != '.')
330     {
331         if (++length == 9)
332             Error("Filename base of %s >8 chars",path);
333         *dest++ = toupper(*src++);
334     }
335 }
336 
337 
338 /*
339 ==============
340 =
341 = ParseNum / ParseHex
342 =
343 ==============
344 */
345 
ParseHex(char * hex)346 int ParseHex(char *hex)
347 {
348     char    *str;
349     int    num;
350 
351     num = 0;
352     str = hex;
353 
354     while (*str)
355     {
356         num <<= 4;
357         if (*str >= '0' && *str <= '9')
358             num += *str-'0';
359         else if (*str >= 'a' && *str <= 'f')
360             num += 10 + *str-'a';
361         else if (*str >= 'A' && *str <= 'F')
362             num += 10 + *str-'A';
363         else
364             Error("Bad hex number: %s",hex);
365         str++;
366     }
367 
368     return num;
369 }
370 
371 
ParseNum(char * str)372 int ParseNum(char *str)
373 {
374     if (str[0] == '$')
375         return ParseHex(str+1);
376     if (str[0] == '0' && str[1] == 'x')
377         return ParseHex(str+2);
378     return atol(str);
379 }
380 
381 
382 
383 
384 // voxelarray format is:
385 //      spritenumber, voxelnumber
386 int aVoxelArray[MAXTILES];
387 
388 // Load all the voxel files using swvoxfil.txt script file
389 // Script file format:
390 
391 //			# - Comment
392 //			spritenumber (in artfile), voxel number, filename
393 //			Ex. 1803 0 medkit2.kvx
394 //			    1804 1 shotgun.kvx
395 //				etc....
396 
LoadKVXFromScript(const char * filename)397 void LoadKVXFromScript(const char *filename)
398 {
399     int lNumber=0,lTile=0;  // lNumber is the voxel no. and lTile is the editart tile being
400     // replaced.
401     char *sName;            // KVS file being loaded in.
402 
403     int grabbed=0;          // Number of lines parsed
404 
405     sName = (char *)Xmalloc(256);    // Up to 256 bytes for path
406     ASSERT(sName != NULL);
407 
408     // zero out the array memory with -1's for pics not being voxelized
409     memset(aVoxelArray,-1,sizeof(aVoxelArray));
410 
411     // Load the file
412     if (!LoadScriptFile(filename)) return;
413 
414     do
415     {
416         GetToken(TRUE); // Crossing a line boundary on the end of line to first token
417         // of a new line is permitted (and expected)
418         if (endofscript)
419             break;
420 
421         lTile = atol(token);
422 
423         GetToken(FALSE);
424         lNumber = atol(token);
425 
426         GetToken(FALSE);
427         strcpy(sName,token);            // Copy the whole token as a file name and path
428 
429         // Load the voxel file into memory
430         if (!qloadkvx(lNumber,sName))
431         {
432             // Store the sprite and voxel numbers for later use
433             aVoxelArray[lTile] = lNumber;   // Voxel num
434         }
435 
436         if (lNumber >= nextvoxid)   // JBF: so voxels in the def file append to the list
437             nextvoxid = lNumber + 1;
438 
439         grabbed++;
440         ASSERT(grabbed < MAXSPRITES);
441 
442     }
443     while (script_p < scriptend_p);
444 
445     Xfree(scriptbuffer);
446     script_p = NULL;
447 }
448 
449 
450 /// MISC ////////////////////////////////////////////////////////////////////
451 
452 /*
453 extern int idleclock,slackerclock;
454 
455 // Watch dog function.  Tracks user's work times.
456 void LogUserTime( SWBOOL bIsLoggingIn )
457 {
458     int size, readsize;
459     time_t time_of_day;
460     char serialid[20],filename[100],fbase[20],buf[26],filetemp[100];
461     FILE *fp;
462     int tothours, totmins, totsecs, gtotalclock=0,gidleclock=0;
463     ldiv_t mins_secs;
464     ldiv_t hrs_mins;
465     int i;
466 
467     char path[] = "o:\\user\\jimn\\logs\\";
468 //	char path[] = "c:\\jim\\sw\\";
469 
470     memset(filename,0,sizeof(filename));
471     memset(fbase,0,sizeof(fbase));
472     memset(serialid,0,sizeof(serialid));
473     memset(buf,0,sizeof(buf));
474     memset(filetemp,0,sizeof(filetemp));
475 
476     // Get the time of day user logged in to build
477     time_of_day = time( NULL );
478 
479     // Get the serial number from the user's disk drive "it's unique!"
480     system("dir > serid.bld");
481     LoadScriptFile("serid.bld");
482 
483     // Go to the serial number
484     for (i=0; i<11; i++)
485     {
486         GetToken (TRUE);
487         if (endofscript)
488             return;
489     }
490 
491     // Copy the token to serialid
492     strcpy(serialid,token);
493 
494     // Free the script memory when done
495     Xfree(scriptbuffer);
496     script_p = NULL;
497 
498     // Build a file name using serial id.
499     strcpy(filename,path);
500     strncpy(fbase,serialid,8);
501     strcat(fbase,".bld");
502     strcat(filename,fbase);
503 
504     // Delete the temp file
505     system("erase serid.bld");
506 
507     // Unhide the file so it can be opened
508     _dos_setfileattr(filename,_A_NORMAL);
509 
510 
511     // Open the file
512     fp = fopen( filename, "a+" );
513 
514     // Opening on the network failed, try putting it on the current disk drive
515     if(fp == NULL)
516     {
517         // Unhide the file so it can be opened/this works if file was created before!
518         _dos_setfileattr(fbase,_A_NORMAL);
519         fp = fopen( fbase, "a+" );
520         strcpy(filetemp,fbase);
521     } else
522         strcpy(filetemp,filename);
523 
524 
525     if( fp == NULL)
526         return;
527     else
528     {
529         if(bIsLoggingIn)
530         {
531             fprintf(fp, "//////////////////////////////\n");
532             fprintf(fp, "User logged into build at: %s", _ctime( &time_of_day, buf ) );
533         }else
534         {
535             totsecs = totalclock/120;	// Convert totalclock to seconds.
536 
537             mins_secs = ldiv( totsecs, 60L );
538             totmins = mins_secs.quot;
539             totsecs = mins_secs.rem;
540 
541             hrs_mins = ldiv( totmins, 60L);
542             tothours = hrs_mins.quot;
543             totmins = hrs_mins.rem;
544 
545             fprintf(fp, "TotalClock: %ld\n",totalclock);
546 #ifdef COMPUTE_TOTALS
547             fprintf(fp, "IdleClock: %ld\n",slackerclock);
548 #endif
549             fprintf(fp, "Time this session: %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs);
550 #ifdef COMPUTE_TOTALS
551             totsecs = (totalclock-slackerclock)/120;	// Convert totalclock to seconds.
552             if(totsecs<=0) totsecs = 0;
553 
554             mins_secs = ldiv( totsecs, 60L );
555             totmins = mins_secs.quot;
556             totsecs = mins_secs.rem;
557 
558             hrs_mins = ldiv( totmins, 60L);
559             tothours = hrs_mins.quot;
560             totmins = hrs_mins.rem;
561             fprintf(fp, "Time - idleclock : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs);
562 #endif
563         }
564 
565         fclose( fp );
566     }
567 
568 #if 1
569     if(!bIsLoggingIn)
570     {
571         // Compute total time for file
572         LoadScriptFile(filetemp);
573 
574         do {
575             GetToken (TRUE);
576 
577             if (endofscript)
578                 break;
579 
580             if(!strcmpi(token,"totalclock:"))
581             {
582                 GetToken(TRUE);
583                 gtotalclock += atol(token);
584             }
585 #if 0
586             if(!strcmpi(token,"idleclock:"))
587             {
588                 GetToken(TRUE);
589                 gidleclock += atol(token);
590             }
591 #endif
592 
593         } while (script_p < scriptend_p);
594 
595         // Free the script memory when done
596         Xfree(scriptbuffer);
597         script_p = NULL;
598 
599         // Open the file
600         fp = fopen( filetemp, "a+" );
601 
602         // Now compute the grand total
603         if(fp != NULL)
604         {
605             totsecs = gtotalclock/120;	// Convert totalclock to seconds.
606 
607             mins_secs = ldiv( totsecs, 60L );
608             totmins = mins_secs.quot;
609             totsecs = mins_secs.rem;
610 
611             hrs_mins = ldiv( totmins, 60L);
612             tothours = hrs_mins.quot;
613             totmins = hrs_mins.rem;
614 
615             fprintf(fp, "\nTotal time so far  : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs);
616 
617 #if 0
618             totsecs = (gtotalclock-gidleclock)/120;	// Convert totalclock to seconds.
619             if(totsecs<=0) totsecs = 0;
620 
621             mins_secs = ldiv( totsecs, 60L );
622             totmins = mins_secs.quot;
623             totsecs = mins_secs.rem;
624 
625             hrs_mins = ldiv( totmins, 60L);
626             tothours = hrs_mins.quot;
627             totmins = hrs_mins.rem;
628 
629             fprintf(fp, "\nTotal actual time  : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs);
630 #endif
631 
632             fclose(fp);
633         }
634     }
635 #endif
636 
637     _dos_setfileattr(filename,_A_HIDDEN);
638 
639 
640 }
641 */
642