~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/cmd/batch.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * CMD - Wine-compatible command line interface - batch interface.
  3  *
  4  * Copyright (C) 1999 D A Pickles
  5  * Copyright (C) 2007 J Edmeades
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  */
 21 
 22 #include "wcmd.h"
 23 #include "wine/debug.h"
 24 
 25 WINE_DEFAULT_DEBUG_CHANNEL(cmd);
 26 
 27 extern int echo_mode;
 28 extern WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
 29 extern BATCH_CONTEXT *context;
 30 extern DWORD errorlevel;
 31 
 32 /****************************************************************************
 33  * WCMD_batch
 34  *
 35  * Open and execute a batch file.
 36  * On entry *command includes the complete command line beginning with the name
 37  * of the batch file (if a CALL command was entered the CALL has been removed).
 38  * *file is the name of the file, which might not exist and may not have the
 39  * .BAT suffix on. Called is 1 for a CALL, 0 otherwise.
 40  *
 41  * We need to handle recursion correctly, since one batch program might call another.
 42  * So parameters for this batch file are held in a BATCH_CONTEXT structure.
 43  *
 44  * To support call within the same batch program, another input parameter is
 45  * a label to goto once opened.
 46  */
 47 
 48 void WCMD_batch (WCHAR *file, WCHAR *command, int called, WCHAR *startLabel, HANDLE pgmHandle) {
 49 
 50 #define WCMD_BATCH_EXT_SIZE 5
 51 
 52   HANDLE h = INVALID_HANDLE_VALUE;
 53   WCHAR string[MAXSTRING];
 54   static const WCHAR extension_batch[][WCMD_BATCH_EXT_SIZE] = {{'.','b','a','t','\0'},
 55                                                                {'.','c','m','d','\0'}};
 56   static const WCHAR extension_exe[WCMD_BATCH_EXT_SIZE] = {'.','e','x','e','\0'};
 57   unsigned int  i;
 58   BATCH_CONTEXT *prev_context;
 59 
 60   if (startLabel == NULL) {
 61     for(i=0; (i<sizeof(extension_batch)/(WCMD_BATCH_EXT_SIZE * sizeof(WCHAR))) &&
 62              (h == INVALID_HANDLE_VALUE); i++) {
 63       strcpyW (string, file);
 64       CharLower (string);
 65       if (strstrW (string, extension_batch[i]) == NULL) strcatW (string, extension_batch[i]);
 66       h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ,
 67                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 68     }
 69     if (h == INVALID_HANDLE_VALUE) {
 70       strcpyW (string, file);
 71       CharLower (string);
 72       if (strstrW (string, extension_exe) == NULL) strcatW (string, extension_exe);
 73       if (GetFileAttributes (string) != INVALID_FILE_ATTRIBUTES) {
 74         WCMD_run_program (command, 0);
 75       } else {
 76         SetLastError (ERROR_FILE_NOT_FOUND);
 77         WCMD_print_error ();
 78       }
 79       return;
 80     }
 81   } else {
 82     DuplicateHandle(GetCurrentProcess(), pgmHandle,
 83                     GetCurrentProcess(), &h,
 84                     0, FALSE, DUPLICATE_SAME_ACCESS);
 85   }
 86 
 87 /*
 88  *      Create a context structure for this batch file.
 89  */
 90 
 91   prev_context = context;
 92   context = LocalAlloc (LMEM_FIXED, sizeof (BATCH_CONTEXT));
 93   context -> h = h;
 94   context -> command = command;
 95   memset(context -> shift_count, 0x00, sizeof(context -> shift_count));
 96   context -> prev_context = prev_context;
 97   context -> skip_rest = FALSE;
 98 
 99   /* If processing a call :label, 'goto' the label in question */
100   if (startLabel) {
101     strcpyW(param1, startLabel);
102     WCMD_goto(NULL);
103   }
104 
105 /*
106  *      Work through the file line by line. Specific batch commands are processed here,
107  *      the rest are handled by the main command processor.
108  */
109 
110   while (context -> skip_rest == FALSE) {
111       CMD_LIST *toExecute = NULL;         /* Commands left to be executed */
112       if (WCMD_ReadAndParseLine(NULL, &toExecute, h) == NULL)
113         break;
114       WCMD_process_commands(toExecute, FALSE, NULL, NULL);
115       WCMD_free_commands(toExecute);
116       toExecute = NULL;
117   }
118   CloseHandle (h);
119 
120 /*
121  *      If invoked by a CALL, we return to the context of our caller. Otherwise return
122  *      to the caller's caller.
123  */
124 
125   LocalFree (context);
126   if ((prev_context != NULL) && (!called)) {
127     prev_context -> skip_rest = TRUE;
128     context = prev_context;
129   }
130   context = prev_context;
131 }
132 
133 /*******************************************************************
134  * WCMD_parameter - extract a parameter from a command line.
135  *
136  *      Returns the 'n'th delimited parameter on the command line (zero-based).
137  *      Parameter is in static storage overwritten on the next call.
138  *      Parameters in quotes (and brackets) are handled.
139  *      Also returns a pointer to the location of the parameter in the command line.
140  */
141 
142 WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where) {
143 
144   int i = 0;
145   static WCHAR param[MAX_PATH];
146   WCHAR *p;
147 
148   if (where != NULL) *where = NULL;
149   p = param;
150   while (TRUE) {
151     switch (*s) {
152       case ' ': /* Skip leading spaces */
153       case '\t': /* Treat tabs as spaces */
154         s++;
155         break;
156       case '"':
157         if (where != NULL && i==n) *where = s;
158         s++;
159         while ((*s != '\0') && (*s != '"')) {
160           *p++ = *s++;
161         }
162         if (i == n) {
163           *p = '\0';
164           return param;
165         }
166         if (*s == '"') s++;
167           param[0] = '\0';
168           i++;
169         p = param;
170         break;
171       /* The code to handle bracketed parms is removed because it should no longer
172          be necessary after the multiline support has been added and the for loop
173          set of data is now parseable individually. */
174       case '\0':
175         return param;
176       default:
177         /* Only return where if it is for the right parameter */
178         if (where != NULL && i==n) *where = s;
179         while ((*s != '\0') && (*s != ' ') && (*s != ',') && (*s != '=') && (*s != '\t')) {
180           *p++ = *s++;
181         }
182         if (i == n && (p!=param)) {
183           *p = '\0';
184           return param;
185         }
186         /* Skip double delimiters, eg. dir a.a,,,,,b.b */
187         if (p != param) {
188           param[0] = '\0';
189           i++;
190         } else {
191           s++; /* Skip delimiter */
192         }
193         p = param;
194     }
195   }
196 }
197 
198 /****************************************************************************
199  * WCMD_fgets
200  *
201  * Get one line from a batch file. We can't use the native f* functions because
202  * of the filename syntax differences between DOS and Unix. Also need to lose
203  * the LF (or CRLF) from the line.
204  */
205 
206 WCHAR *WCMD_fgets (WCHAR *s, int noChars, HANDLE h) {
207 
208   DWORD bytes;
209   BOOL status;
210   WCHAR *p;
211 
212   p = s;
213   do {
214     status = WCMD_ReadFile (h, s, 1, &bytes, NULL);
215     if ((status == 0) || ((bytes == 0) && (s == p))) return NULL;
216     if (*s == '\n') bytes = 0;
217     else if (*s != '\r') {
218       s++;
219       noChars--;
220     }
221     *s = '\0';
222   } while ((bytes == 1) && (noChars > 1));
223   return p;
224 }
225 
226 /* WCMD_splitpath - copied from winefile as no obvious way to use it otherwise */
227 void WCMD_splitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext)
228 {
229         const WCHAR* end; /* end of processed string */
230         const WCHAR* p;  /* search pointer */
231         const WCHAR* s;  /* copy pointer */
232 
233         /* extract drive name */
234         if (path[0] && path[1]==':') {
235                 if (drv) {
236                         *drv++ = *path++;
237                         *drv++ = *path++;
238                         *drv = '\0';
239                 }
240         } else if (drv)
241                 *drv = '\0';
242 
243         /* search for end of string or stream separator */
244         for(end=path; *end && *end!=':'; )
245                 end++;
246 
247         /* search for begin of file extension */
248         for(p=end; p>path && *--p!='\\' && *p!='/'; )
249                 if (*p == '.') {
250                         end = p;
251                         break;
252                 }
253 
254         if (ext)
255                 for(s=end; (*ext=*s++); )
256                         ext++;
257 
258         /* search for end of directory name */
259         for(p=end; p>path; )
260                 if (*--p=='\\' || *p=='/') {
261                         p++;
262                         break;
263                 }
264 
265         if (name) {
266                 for(s=p; s<end; )
267                         *name++ = *s++;
268 
269                 *name = '\0';
270         }
271 
272         if (dir) {
273                 for(s=path; s<p; )
274                         *dir++ = *s++;
275 
276                 *dir = '\0';
277         }
278 }
279 
280 /****************************************************************************
281  * WCMD_HandleTildaModifiers
282  *
283  * Handle the ~ modifiers when expanding %0-9 or (%a-z in for command)
284  *    %~xxxxxV  (V=0-9 or A-Z)
285  * Where xxxx is any combination of:
286  *    ~ - Removes quotes
287  *    f - Fully qualified path (assumes current dir if not drive\dir)
288  *    d - drive letter
289  *    p - path
290  *    n - filename
291  *    x - file extension
292  *    s - path with shortnames
293  *    a - attributes
294  *    t - date/time
295  *    z - size
296  *    $ENVVAR: - Searches ENVVAR for (contents of V) and expands to fully
297  *                   qualified path
298  *
299  *  To work out the length of the modifier:
300  *
301  *  Note: In the case of %0-9 knowing the end of the modifier is easy,
302  *    but in a for loop, the for end WCHARacter may also be a modifier
303  *    eg. for %a in (c:\a.a) do echo XXX
304  *             where XXX = %~a    (just ~)
305  *                         %~aa   (~ and attributes)
306  *                         %~aaxa (~, attributes and extension)
307  *                   BUT   %~aax  (~ and attributes followed by 'x')
308  *
309  *  Hence search forwards until find an invalid modifier, and then
310  *  backwards until find for variable or 0-9
311  */
312 void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable, WCHAR *forValue, BOOL justFors) {
313 
314 #define NUMMODIFIERS 11
315   static const WCHAR validmodifiers[NUMMODIFIERS] = {
316         '~', 'f', 'd', 'p', 'n', 'x', 's', 'a', 't', 'z', '$'
317   };
318   static const WCHAR space[] = {' ', '\0'};
319 
320   WIN32_FILE_ATTRIBUTE_DATA fileInfo;
321   WCHAR  outputparam[MAX_PATH];
322   WCHAR  finaloutput[MAX_PATH];
323   WCHAR  fullfilename[MAX_PATH];
324   WCHAR  thisoutput[MAX_PATH];
325   WCHAR  *pos            = *start+1;
326   WCHAR  *firstModifier  = pos;
327   WCHAR  *lastModifier   = NULL;
328   int   modifierLen     = 0;
329   BOOL  finished        = FALSE;
330   int   i               = 0;
331   BOOL  exists          = TRUE;
332   BOOL  skipFileParsing = FALSE;
333   BOOL  doneModifier    = FALSE;
334 
335   /* Search forwards until find invalid character modifier */
336   while (!finished) {
337 
338     /* Work on the previous character */
339     if (lastModifier != NULL) {
340 
341       for (i=0; i<NUMMODIFIERS; i++) {
342         if (validmodifiers[i] == *lastModifier) {
343 
344           /* Special case '$' to skip until : found */
345           if (*lastModifier == '$') {
346             while (*pos != ':' && *pos) pos++;
347             if (*pos == 0x00) return; /* Invalid syntax */
348             pos++;                    /* Skip ':'       */
349           }
350           break;
351         }
352       }
353 
354       if (i==NUMMODIFIERS) {
355         finished = TRUE;
356       }
357     }
358 
359     /* Save this one away */
360     if (!finished) {
361       lastModifier = pos;
362       pos++;
363     }
364   }
365 
366   while (lastModifier > firstModifier) {
367     WINE_TRACE("Looking backwards for parameter id: %s / %s\n",
368                wine_dbgstr_w(lastModifier), wine_dbgstr_w(forVariable));
369 
370     if (!justFors && context && (*lastModifier >= '' && *lastModifier <= '9')) {
371       /* Its a valid parameter identifier - OK */
372       break;
373 
374     } else if (forVariable && *lastModifier == *(forVariable+1)) {
375       /* Its a valid parameter identifier - OK */
376       break;
377 
378     } else {
379       lastModifier--;
380     }
381   }
382   if (lastModifier == firstModifier) return; /* Invalid syntax */
383 
384   /* Extract the parameter to play with */
385   if ((*lastModifier >= '' && *lastModifier <= '9')) {
386     strcpyW(outputparam, WCMD_parameter (context -> command,
387                  *lastModifier-'' + context -> shift_count[*lastModifier-''], NULL));
388   } else {
389     strcpyW(outputparam, forValue);
390   }
391 
392   /* So now, firstModifier points to beginning of modifiers, lastModifier
393      points to the variable just after the modifiers. Process modifiers
394      in a specific order, remembering there could be duplicates           */
395   modifierLen = lastModifier - firstModifier;
396   finaloutput[0] = 0x00;
397 
398   /* Useful for debugging purposes: */
399   /*printf("Modifier string '%*.*s' and variable is %c\n Param starts as '%s'\n",
400              (modifierLen), (modifierLen), firstModifier, *lastModifier,
401              outputparam);*/
402 
403   /* 1. Handle '~' : Strip surrounding quotes */
404   if (outputparam[0]=='"' &&
405       memchrW(firstModifier, '~', modifierLen) != NULL) {
406     int len = strlenW(outputparam);
407     if (outputparam[len-1] == '"') {
408         outputparam[len-1]=0x00;
409         len = len - 1;
410     }
411     memmove(outputparam, &outputparam[1], (len * sizeof(WCHAR))-1);
412   }
413 
414   /* 2. Handle the special case of a $ */
415   if (memchrW(firstModifier, '$', modifierLen) != NULL) {
416     /* Special Case: Search envar specified in $[envvar] for outputparam
417        Note both $ and : are guaranteed otherwise check above would fail */
418     WCHAR *start = strchrW(firstModifier, '$') + 1;
419     WCHAR *end   = strchrW(firstModifier, ':');
420     WCHAR env[MAX_PATH];
421     WCHAR fullpath[MAX_PATH];
422 
423     /* Extract the env var */
424     memcpy(env, start, (end-start) * sizeof(WCHAR));
425     env[(end-start)] = 0x00;
426 
427     /* If env var not found, return empty string */
428     if ((GetEnvironmentVariable(env, fullpath, MAX_PATH) == 0) ||
429         (SearchPath(fullpath, outputparam, NULL,
430                     MAX_PATH, outputparam, NULL) == 0)) {
431       finaloutput[0] = 0x00;
432       outputparam[0] = 0x00;
433       skipFileParsing = TRUE;
434     }
435   }
436 
437   /* After this, we need full information on the file,
438     which is valid not to exist.  */
439   if (!skipFileParsing) {
440     if (GetFullPathName(outputparam, MAX_PATH, fullfilename, NULL) == 0)
441       return;
442 
443     exists = GetFileAttributesExW(fullfilename, GetFileExInfoStandard,
444                                   &fileInfo);
445 
446     /* 2. Handle 'a' : Output attributes */
447     if (exists &&
448         memchrW(firstModifier, 'a', modifierLen) != NULL) {
449 
450       WCHAR defaults[] = {'-','-','-','-','-','-','-','-','-','\0'};
451       doneModifier = TRUE;
452       strcpyW(thisoutput, defaults);
453       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
454         thisoutput[0]='d';
455       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
456         thisoutput[1]='r';
457       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
458         thisoutput[2]='a';
459       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
460         thisoutput[3]='h';
461       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
462         thisoutput[4]='s';
463       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
464         thisoutput[5]='c';
465       /* FIXME: What are 6 and 7? */
466       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
467         thisoutput[8]='l';
468       strcatW(finaloutput, thisoutput);
469     }
470 
471     /* 3. Handle 't' : Date+time */
472     if (exists &&
473         memchrW(firstModifier, 't', modifierLen) != NULL) {
474 
475       SYSTEMTIME systime;
476       int datelen;
477 
478       doneModifier = TRUE;
479       if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
480 
481       /* Format the time */
482       FileTimeToSystemTime(&fileInfo.ftLastWriteTime, &systime);
483       GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime,
484                         NULL, thisoutput, MAX_PATH);
485       strcatW(thisoutput, space);
486       datelen = strlenW(thisoutput);
487       GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &systime,
488                         NULL, (thisoutput+datelen), MAX_PATH-datelen);
489       strcatW(finaloutput, thisoutput);
490     }
491 
492     /* 4. Handle 'z' : File length */
493     if (exists &&
494         memchrW(firstModifier, 'z', modifierLen) != NULL) {
495       /* FIXME: Output full 64 bit size (sprintf does not support I64 here) */
496       ULONG/*64*/ fullsize = /*(fileInfo.nFileSizeHigh << 32) +*/
497                                   fileInfo.nFileSizeLow;
498       static const WCHAR fmt[] = {'%','u','\0'};
499 
500       doneModifier = TRUE;
501       if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
502       wsprintf(thisoutput, fmt, fullsize);
503       strcatW(finaloutput, thisoutput);
504     }
505 
506     /* 4. Handle 's' : Use short paths (File doesn't have to exist) */
507     if (memchrW(firstModifier, 's', modifierLen) != NULL) {
508       if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
509       /* Don't flag as doneModifier - %~s on its own is processed later */
510       GetShortPathName(outputparam, outputparam,
511                        sizeof(outputparam)/sizeof(outputparam[0]));
512     }
513 
514     /* 5. Handle 'f' : Fully qualified path (File doesn't have to exist) */
515     /*      Note this overrides d,p,n,x                                 */
516     if (memchrW(firstModifier, 'f', modifierLen) != NULL) {
517       doneModifier = TRUE;
518       if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
519       strcatW(finaloutput, fullfilename);
520     } else {
521 
522       WCHAR drive[10];
523       WCHAR dir[MAX_PATH];
524       WCHAR fname[MAX_PATH];
525       WCHAR ext[MAX_PATH];
526       BOOL doneFileModifier = FALSE;
527 
528       if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
529 
530       /* Split into components */
531       WCMD_splitpath(fullfilename, drive, dir, fname, ext);
532 
533       /* 5. Handle 'd' : Drive Letter */
534       if (memchrW(firstModifier, 'd', modifierLen) != NULL) {
535         strcatW(finaloutput, drive);
536         doneModifier = TRUE;
537         doneFileModifier = TRUE;
538       }
539 
540       /* 6. Handle 'p' : Path */
541       if (memchrW(firstModifier, 'p', modifierLen) != NULL) {
542         strcatW(finaloutput, dir);
543         doneModifier = TRUE;
544         doneFileModifier = TRUE;
545       }
546 
547       /* 7. Handle 'n' : Name */
548       if (memchrW(firstModifier, 'n', modifierLen) != NULL) {
549         strcatW(finaloutput, fname);
550         doneModifier = TRUE;
551         doneFileModifier = TRUE;
552       }
553 
554       /* 8. Handle 'x' : Ext */
555       if (memchrW(firstModifier, 'x', modifierLen) != NULL) {
556         strcatW(finaloutput, ext);
557         doneModifier = TRUE;
558         doneFileModifier = TRUE;
559       }
560 
561       /* If 's' but no other parameter, dump the whole thing */
562       if (!doneFileModifier &&
563           memchrW(firstModifier, 's', modifierLen) != NULL) {
564         doneModifier = TRUE;
565         if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
566         strcatW(finaloutput, outputparam);
567       }
568     }
569   }
570 
571   /* If No other modifier processed,  just add in parameter */
572   if (!doneModifier) strcpyW(finaloutput, outputparam);
573 
574   /* Finish by inserting the replacement into the string */
575   WCMD_strsubstW(*start, lastModifier+1, finaloutput, -1);
576 }
577 
578 /*******************************************************************
579  * WCMD_call - processes a batch call statement
580  *
581  *      If there is a leading ':', calls within this batch program
582  *      otherwise launches another program.
583  */
584 void WCMD_call (WCHAR *command) {
585 
586   /* Run other program if no leading ':' */
587   if (*command != ':') {
588     WCMD_run_program(command, 1);
589   } else {
590 
591     WCHAR gotoLabel[MAX_PATH];
592 
593     strcpyW(gotoLabel, param1);
594 
595     if (context) {
596 
597       LARGE_INTEGER li;
598 
599       /* Save the current file position, call the same file,
600          restore position                                    */
601       li.QuadPart = 0;
602       li.u.LowPart = SetFilePointer(context -> h, li.u.LowPart,
603                      &li.u.HighPart, FILE_CURRENT);
604 
605       WCMD_batch (param1, command, 1, gotoLabel, context->h);
606 
607       SetFilePointer(context -> h, li.u.LowPart,
608                      &li.u.HighPart, FILE_BEGIN);
609     } else {
610       WCMD_output_asis( WCMD_LoadMessage(WCMD_CALLINSCRIPT));
611     }
612   }
613 }
614 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.