Subversion Repositories DevTools

Rev

Rev 1026 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1024 ghuddy 1
 
2
 
3
#include <stdarg.h>
4
#include <ctype.h>
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <string.h>
8
#include <process.h>
9
#include "CRTDBG.H"
10
 
11
#include "version.h"
12
 
13
#ifndef TRUE
14
#define TRUE (-1)
15
#endif
16
 
17
#ifndef FALSE
18
#define FALSE (0)
19
#endif
20
 
21
#define MAX_LINE_LEN    1024
22
 
23
typedef enum {
24
   BIG_ENDIAN, LITTLE_ENDIAN
25
} endian_t;
26
 
27
 
28
 
29
/*
30
* GLOBAL DATA
31
*/
32
FILE *op_stream;
33
FILE *ip_stream;
34
FILE *cmd_stream;
35
 
36
int    i_op_file_opened = FALSE;
37
int    i_ip_file_opened = FALSE;
38
 
39
char   cmd_line[MAX_LINE_LEN];
40
 
41
int    i_had_input_stream_errors = FALSE;
42
 
43
fpos_t ip_stream_pos;
44
int    ip_stream_pos_valid = FALSE;
45
int    ip_stream_pos_cmdLineNumber;
46
 
47
long cmdLineNum = 0;
48
 
49
int endianism = BIG_ENDIAN;
50
 
51
long op_stream_tell[10];
52
long base_reference = 0;
53
 
54
int debug_level = 0;
55
 
56
int mustAbort = 0;
57
 
1026 dpurdie 58
int exitCode = 0;
59
 
1024 ghuddy 60
typedef struct
61
{
62
   int cmdLineNumber;
63
   fpos_t filepos;
64
} stack_t;
65
 
66
#define MAX_STACK 50
67
stack_t stack[MAX_STACK];
68
int stackptr = -1;
69
int skippingPastSub = 0;
70
 
71
 
72
 
73
#define DEBUG_CONTROL_CMD_MASK      0x0001
74
#define DEBUG_OUTPUT_CMD_MASK       0x0002
75
#define DEBUG_INPUT_CMD_MASK        0x0004
76
 
77
 
78
 
79
 
80
/**************************************************************************/
81
/* COMMAND REPEAT support
82
*/
83
 
84
typedef struct {
85
   int    cmdLineNumber;
86
   fpos_t cmd_stream_pos;
87
   int    cmd_stream_repeat;
88
} cmd_rep_type;
89
 
90
#define MAX_NEST_LEVEL 10
91
 
92
cmd_rep_type cmd_repeat_stack[MAX_NEST_LEVEL];
93
 
94
int cmd_repeat_nest_level = -1;
95
 
96
/**************************************************************************/
97
 
98
/* PROTOTYPES */
1028 dpurdie 99
void ins_quad(unsigned __int64 value);
1024 ghuddy 100
void ins_long(unsigned long value);
101
void ins_word(unsigned long value);
102
void ins_byte(unsigned long value);
103
 
104
 
105
/**************************************************************************/
106
 
107
char * skip_to_spaces(char * strptr)
108
{
109
   while ( (isspace(*strptr) == 0) && (*strptr != 0) )
110
      strptr++;
111
 
112
   return strptr;
113
}
114
 
115
char * skip_past_spaces(char * strptr)
116
{
117
   while ( (isspace(*strptr) != 0) && (*strptr != 0) )
118
      strptr++;
119
 
120
   return strptr;
121
}
122
 
123
 
124
char * next_value(char * arg_ptr, unsigned long * value, int * got_a_value)
125
{
126
   char * endp;
127
 
128
   unsigned long arg_val = 0;
129
 
130
   *got_a_value = FALSE;
131
 
132
   // skip to the first numeric
133
   while ( ((*arg_ptr < '0') || (*arg_ptr > '9'))
134
      &&
135
      (*arg_ptr != 0) ) {
136
      arg_ptr++;
137
   }
138
 
139
   arg_val = strtoul( arg_ptr, &endp, 0 );
140
 
141
   *value = arg_val;
142
 
143
   if (endp > arg_ptr)
144
      *got_a_value = TRUE;
145
 
146
   arg_ptr = endp;
147
 
148
   return arg_ptr;
149
}
150
 
1028 dpurdie 151
char * next_value64(char * arg_ptr, unsigned __int64 * value, int * got_a_value)
152
{
153
   char * endp;
154
   unsigned __int64 calc = 0;
155
 
156
   unsigned long arg_val = 0;
157
 
158
   *got_a_value = FALSE;
159
 
160
   // skip to the first numeric
161
   while ( ((*arg_ptr < '0') || (*arg_ptr > '9')) && (*arg_ptr != 0) ) {
162
        arg_ptr++;
163
   }
164
 
165
   // Process Data
166
   endp = arg_ptr;
167
   while ( ((*endp >= '0') && (*endp <= '9')) && (*endp != 0) ) {
168
        calc = calc * 10;
169
        calc += *endp - '0';
170
        endp++;
171
   }
172
 
173
   *value = calc;
174
 
175
   if (endp > arg_ptr)
176
      *got_a_value = TRUE;
177
 
178
   arg_ptr = endp;
179
 
180
   return arg_ptr;
181
}
182
 
183
 
1024 ghuddy 184
char * remove_trailing_spaces(char * pStr)
185
{
186
   int str_len = strlen(pStr);
187
   if (str_len > 0)
188
   {
189
      while ( (--str_len >= 0) && (pStr[str_len] == ' ') )
190
      {
191
         pStr[str_len] = 0;
192
      }
193
   }
194
   return pStr;
195
}
196
 
197
void strip_trailing_comment(char * pStr)
198
{
199
   char * comment_ptr;
200
 
201
   comment_ptr = strchr(pStr, '#');
202
 
203
   if (comment_ptr != NULL)
204
      *comment_ptr = 0;
205
}
206
 
207
void strip_trailing_comment_and_spaces(char * pStr)
208
{
209
   char * comment_ptr;
210
 
211
   comment_ptr = strchr(pStr, '#');
212
 
213
   if (comment_ptr != NULL)
214
      *comment_ptr = 0;
215
 
216
   (void)remove_trailing_spaces(pStr);
217
}
218
 
219
 
220
char * remove_newline_char(char * pStr)
221
{
222
   // look for a \n at the end of the string, and if found, remove it
223
   int str_len = strlen(pStr);
224
   if (str_len > 0)
225
   {
226
      if (pStr[str_len - 1] == '\n')
227
      {
228
         pStr[str_len - 1] = 0;
229
      }
230
   }
231
 
232
   return pStr;
233
}
234
 
235
char * fgets_and_strip_newline(char * s, int n, FILE * stream)
236
{
237
   char * retVal;
238
 
239
   if ((retVal = fgets( s, n, stream )) != NULL)
240
   {
241
      remove_newline_char(s);
242
   }
243
 
244
   return retVal;
245
}
246
 
247
 
248
/**************************************************************************/
249
 
250
/*
251
* Errors - Where output file will be compromised
252
* Warnings - less serious ??
253
*/
254
 
255
void ERROR(char * str)
256
{
257
   printf("ERROR   Line %05ld : %s\n", cmdLineNum, str);
258
   mustAbort = 1;
259
}
260
 
261
void WARNING(char * str)
262
{
263
   printf("WARNING Line %05ld : %s\n", cmdLineNum, str);
264
}
265
 
266
 
267
void DEBUG( int level, char * fmt, ... )
268
{
269
   if (level & debug_level)
270
   {
271
      char buff[256];
272
      long offset;
273
      va_list arg;
274
 
275
      va_start(arg, fmt);
276
      vsprintf( buff, fmt, arg );
277
      if (i_op_file_opened)
278
      {
279
         offset = ftell(op_stream);
280
         printf( "DEBUG   CmdFileLine:%05ld, OutputFilePos:%06ld : %s\n", cmdLineNum, offset, buff );
281
      }
282
      else
283
      {
284
         printf( "DEBUG   CmdFileLine:%05ld, OutputFilePos:------ : %s\n", cmdLineNum, buff );
285
      }
286
      va_end(arg);
287
   }
288
}
289
 
290
/**************************************************************************/
291
 
292
long adjusted_op_stream_tell( long var )
293
{
294
   if (op_stream_tell[var] >= base_reference)
295
   {
296
      return op_stream_tell[var] - base_reference;
297
   }
298
   else
299
   {
300
      ERROR("Negative offset");
301
   }
302
 
303
   return op_stream_tell[var];
304
}
305
 
306
/**************************************************************************/
307
 
308
void fn_DEBUG(char * arg_ptr)
309
{
310
   unsigned long value;
311
   int got_a_value = TRUE;
312
 
313
   (void)next_value(arg_ptr, &value, &got_a_value);
314
   if (got_a_value)
315
   {
316
      debug_level = value;
317
   }
318
}
319
 
320
/**************************************************************************/
321
 
322
void fn_DUP(char * arg_ptr)
323
{
324
   unsigned long count, value, i;
325
   int           got_a_value;
326
 
327
   DEBUG( DEBUG_OUTPUT_CMD_MASK, "DUP %s", arg_ptr );
328
 
329
   arg_ptr = next_value(arg_ptr, &count, &got_a_value);
330
   if (got_a_value)
331
   {
332
      arg_ptr = next_value(arg_ptr, &value, &got_a_value);
333
      if (got_a_value)
334
      {
335
         if (value <= 255)
336
         {
337
            for (i=0; i<count; i++)
338
               fputc(value, op_stream);
339
         }
340
         else
341
         {
342
            ERROR("Bad value in DUP command");
343
         }
344
         return;
345
      }
346
   }
347
   ERROR("Bad/missing count/value in DUP command");
348
}
349
 
350
 
351
void fn_DB(char * arg_ptr)
352
{
353
   unsigned long value;
354
   int got_a_value = TRUE;
355
 
356
   DEBUG( DEBUG_OUTPUT_CMD_MASK, "DB %s", arg_ptr );
357
 
358
   while ( (*arg_ptr != 0) && (got_a_value) )
359
   {
360
      arg_ptr = next_value(arg_ptr, &value, &got_a_value);
361
      if (got_a_value) {
362
         if (value <= 255)
363
         {
364
            fputc(value, op_stream);
365
         }
366
         else
367
         {
368
            ERROR("Bad value in DB command (values must be 0..255)");
369
         }
370
      }
371
   }
372
}
373
 
374
 
375
void fn_DW(char * arg_ptr)
376
{
377
   unsigned long value;
378
   int got_a_value = TRUE;
379
 
380
   DEBUG( DEBUG_OUTPUT_CMD_MASK, "DW %s", arg_ptr );
381
 
382
   while ( (*arg_ptr != 0) && (got_a_value) )
383
   {
384
      arg_ptr = next_value(arg_ptr, &value, &got_a_value);
385
      if (got_a_value)
386
      {
387
         if (value <= 65535)
388
         {
389
            ins_word(value);
390
         }
391
         else
392
         {
393
            ERROR("Bad value in DW command (values must be 0..65535)");
394
         }
395
      }
396
   }
397
}
398
 
399
 
400
void fn_DL(char * arg_ptr)
401
{
402
   unsigned long value;
403
   int got_a_value = TRUE;
404
 
405
   DEBUG( DEBUG_OUTPUT_CMD_MASK, "DL %s", arg_ptr );
406
 
407
   while ( (*arg_ptr != 0) && (got_a_value) )
408
   {
409
      arg_ptr = next_value(arg_ptr, &value, &got_a_value);
410
      if (got_a_value)
411
      {
412
         ins_long(value);
413
      }
414
   }
415
}
416
 
1028 dpurdie 417
void fn_DQ(char * arg_ptr)
418
{
419
   unsigned __int64  value;
420
   int got_a_value = TRUE;
1024 ghuddy 421
 
1028 dpurdie 422
   DEBUG( DEBUG_OUTPUT_CMD_MASK, "DQ %s", arg_ptr );
423
 
424
   while ( (*arg_ptr != 0) && (got_a_value) )
425
   {
426
      arg_ptr = next_value64(arg_ptr, &value, &got_a_value);
427
      if (got_a_value)
428
      {
429
         ins_quad(value);
430
      }
431
   }
432
}
433
 
434
 
435
 
1024 ghuddy 436
void fn_TEXT(char * arg_ptr)
437
{
438
   if (*arg_ptr != 0)
439
   {
440
      DEBUG( DEBUG_OUTPUT_CMD_MASK, "TEXT %s", arg_ptr );
441
 
442
      while (*arg_ptr != 0)
443
         fputc(*arg_ptr++, op_stream);
444
   }
445
   else
446
   {
447
      ERROR("Missing text from TEXT command");
448
   }
449
}
450
 
451
 
452
void fn_NTEXT(char * arg_ptr)
453
{
454
   char * initial_arg_ptr = arg_ptr;
455
 
456
   unsigned long value;
457
   int got_a_value;
458
 
459
   arg_ptr = next_value(arg_ptr, &value, &got_a_value);
460
   if (got_a_value)
461
   {
462
      arg_ptr++;  /* skip past ',' character */
463
 
464
      if (*arg_ptr != 0)
465
      {
466
         DEBUG( DEBUG_OUTPUT_CMD_MASK, "NTEXT %s", initial_arg_ptr );
467
 
468
         /* feed text to output */
469
         while ( (*arg_ptr != 0) && (value > 0) )
470
         {
471
            fputc(*arg_ptr++, op_stream);
472
            value--;
473
         }
474
 
475
         /* Pad output with 0's if necessary */
476
         while ( value > 0)
477
         {
478
            fputc(0, op_stream);
479
            value--;
480
         }
481
      }
482
      else
483
      {
484
         ERROR("Missing text from NTEXT command");
485
      }
486
   }
487
   else
488
   {
489
      ERROR("Bad/missing count/value in NTEXT command");
490
   }
491
}
492
 
493
 
1026 dpurdie 494
void fn_ZTEXT(char * arg_ptr)
495
{
496
   char * initial_arg_ptr = arg_ptr;
497
 
498
   unsigned long value;
499
   int got_a_value;
500
 
501
   arg_ptr = next_value(arg_ptr, &value, &got_a_value);
502
   if (got_a_value)
503
   {
504
      if ( value <= 1 )
505
      {
506
         ERROR("ZTEXT length too short");
507
      }
508
      arg_ptr++;  /* skip past ',' character */
509
 
510
      if (*arg_ptr != 0)
511
      {
512
         DEBUG( DEBUG_OUTPUT_CMD_MASK, "ZTEXT %s", initial_arg_ptr );
513
 
514
         /* feed text to output */
515
         while ( (*arg_ptr != 0) && (value > 1) )
516
         {
517
            fputc(*arg_ptr++, op_stream);
518
            value--;
519
         }
520
 
521
         /* Pad output with 0's if necessary */
522
         while ( value > 0)
523
         {
524
            fputc(0, op_stream);
525
            value--;
526
         }
527
      }
528
      else
529
      {
530
         ERROR("Missing text from ZTEXT command");
531
      }
532
   }
533
   else
534
   {
535
      ERROR("Bad/missing count/value in ZTEXT command");
536
   }
537
}
538
 
539
 
1024 ghuddy 540
/**************************************************************************/
541
 
542
void fn_FEED(char * arg_ptr)
543
{
544
   unsigned long count, i;
545
   int c, got_a_value;
546
 
547
   (void)next_value(arg_ptr, &count, &got_a_value);
548
   if (got_a_value)
549
   {
550
      DEBUG( DEBUG_OUTPUT_CMD_MASK | DEBUG_INPUT_CMD_MASK, "FEED %s", arg_ptr );
551
 
552
      for (i=0; i<count; i++)
553
      {
554
         c = fgetc(ip_stream);
555
         if (c != EOF)
556
            fputc(c, op_stream);
557
         else
558
         {
559
            i_had_input_stream_errors = TRUE;
560
            break;
561
         }
562
      }
563
   }
564
   else
565
   {
566
      ERROR("Bad/missing count value in FEED command");
567
   }
568
}
569
 
570
 
571
void fn_SKIP(char * arg_ptr)
572
{
573
   unsigned long count, i;
574
   int    c, got_a_value;
575
 
576
 
577
   (void)next_value(arg_ptr, &count, &got_a_value);
578
   if (got_a_value)
579
   {
580
      DEBUG( DEBUG_INPUT_CMD_MASK, "SKIP %s", arg_ptr );
581
 
582
      for (i=0; i<count; i++)
583
      {
584
         c = fgetc(ip_stream);
585
         if (c == EOF)
586
         {
587
            i_had_input_stream_errors = TRUE;
588
            break;
589
         }
590
      }
591
   }
592
   else
593
   {
594
      ERROR("Bad/missing count value in SKIP command");
595
   }
596
}
597
 
598
 
599
void fn_MARK(char * arg_ptr)
600
{
601
 
602
   if (fgetpos(ip_stream, &ip_stream_pos) == 0)
603
   {
604
      DEBUG( DEBUG_CONTROL_CMD_MASK, "MARK %s", arg_ptr );
605
 
606
      ip_stream_pos_cmdLineNumber = cmdLineNum;
607
      ip_stream_pos_valid = TRUE;
608
   }
609
   else
610
   {
611
      ip_stream_pos_valid = FALSE;
612
      ERROR("MARK command failed on input file");
613
   }
614
}
615
 
616
void fn_REWIND(char * arg_ptr)
617
{
618
   if (ip_stream_pos_valid)
619
   {
620
      if (fsetpos(ip_stream, &ip_stream_pos))
621
      {
622
         ERROR("REWIND command failed on input file");
623
      }
624
      else
625
      {
626
         cmdLineNum = ip_stream_pos_cmdLineNumber;
627
 
628
         DEBUG( DEBUG_CONTROL_CMD_MASK, "REWIND %s (pos:%ld)", arg_ptr, ip_stream_pos );
629
      }
630
   }
631
   else
632
   {
633
      ERROR("REWIND could not be matched to a previous MARK command");
634
   }
635
}
636
 
637
/**************************************************************************/
638
 
639
void fn_SEEKSTART(char * arg_ptr)
640
{
641
   unsigned long offset;
642
   int    got_a_value;
643
 
644
   (void)next_value(arg_ptr, &offset, &got_a_value);
645
   if (got_a_value)
646
   {
647
      if (fseek(op_stream, (long)offset, SEEK_SET))
648
      {
649
         ERROR("SEEKSTART command failed on output file");
650
      }
651
      else
652
      {
653
         DEBUG( DEBUG_CONTROL_CMD_MASK, "SEEKSTART %s (offset:%ld)", arg_ptr, offset );
654
      }
655
   }
656
   else
657
   {
658
      ERROR("Bad/missing offset value in SEEKSTART command");
659
   }
660
}
661
 
662
void fn_SEEKEND(char * arg_ptr)
663
{
664
   unsigned long offset;
665
   int    got_a_value;
666
 
667
   (void)next_value(arg_ptr, &offset, &got_a_value);
668
   if (got_a_value)
669
   {
670
      DEBUG( DEBUG_CONTROL_CMD_MASK, "SEEKEND %s (offset:%ld)", arg_ptr, offset );
671
 
672
      if (fseek(op_stream, (long)offset, SEEK_END))
673
      {
674
         ERROR("SEEKEND command failed on output file");
675
      }
676
   }
677
   else
678
   {
679
      ERROR("Bad/missing offset value in SEEKEND command");
680
   }
681
}
682
 
683
void fn_SEEKCUR(char * arg_ptr)
684
{
685
   unsigned long offset;
686
   int    got_a_value;
687
 
688
   (void)next_value(arg_ptr, &offset, &got_a_value);
689
   if (got_a_value)
690
   {
691
      DEBUG( DEBUG_CONTROL_CMD_MASK, "SEEKCUR %s (offset:%ld)", arg_ptr, offset );
692
 
693
      if (fseek(op_stream, (long)offset, SEEK_CUR))
694
      {
695
         ERROR("SEEKCUR command failed on output file");
696
      }
697
   }
698
   else
699
   {
700
      ERROR("Bad/missing offset value in SEEKCUR command");
701
   }
702
}
703
 
704
 
705
void fn_TELL(char * arg_ptr)
706
{
707
   long offset;
708
 
709
   unsigned long var;
710
   int    got_a_value;
711
 
712
   (void)next_value(arg_ptr, &var, &got_a_value);
713
   if (got_a_value)
714
   {
715
      if (var >= 1 && var <= 10)
716
      {
717
         offset = ftell(op_stream);
718
         if (offset == -1L)
719
         {
720
            ERROR("TELL command failed on output file");
721
         }
722
         else
723
         {
724
            op_stream_tell[var] = offset;
725
 
726
            DEBUG( DEBUG_CONTROL_CMD_MASK, "TELL %s (result:%ld)", arg_ptr, offset );
727
         }
728
      }
729
      else
730
      {
731
         ERROR("Out of range variable number in TELL command (must be 1..10)");
732
      }
733
   }
734
   else
735
   {
736
      ERROR("Bad/missing variable number in TELL command");
737
   }
738
}
739
 
740
void fn_SEEKTELL(char * arg_ptr)
741
{
742
   unsigned long var;
743
   int    got_a_value;
744
 
745
   (void)next_value(arg_ptr, &var, &got_a_value);
746
   if (got_a_value)
747
   {
748
      if (var >= 1 && var <= 10)
749
      {
750
         DEBUG( DEBUG_CONTROL_CMD_MASK, "SEEKTELL %s (offset:%ld)", arg_ptr, op_stream_tell[var] );
751
 
752
         if (fseek(op_stream, op_stream_tell[var], SEEK_SET))
753
         {
754
            ERROR("SEEKTELL command failed on output file");
755
         }
756
      }
757
      else
758
      {
759
         ERROR("Out of range variable number in SEEKTELL command (must be 1..10)");
760
      }
761
   }
762
   else
763
   {
764
      ERROR("Bad/missing variable number in SEEKTELL command");
765
   }
766
}
767
 
768
 
769
void fn_ALIGNMENT(char * arg_ptr, unsigned long requested_alignment)
770
{
771
   long offset;
772
 
773
   offset = ftell(op_stream);
774
   if (offset == -1L)
775
   {
776
      ERROR("ALIGNMENT command failed on output file (ftell)");
777
   }
778
   else
779
   {
780
      unsigned long required_alignment;
781
      int    got_a_value;
782
 
783
      (void)next_value(arg_ptr, &required_alignment, &got_a_value);
784
      if (got_a_value || requested_alignment)
785
      {
786
         // allow caller to override the alignment value
787
         if (requested_alignment)
788
            required_alignment = requested_alignment;
789
 
790
         if (required_alignment == 2 || required_alignment == 4 || required_alignment == 8)
791
         {
792
            if (offset & (required_alignment - 1))
793
            {
794
               int padding_required = required_alignment - (offset & (required_alignment - 1));
795
 
796
               // find out the current output file size
797
               if (0==fseek(op_stream, 0, SEEK_END))
798
               {
799
                  long filesize = ftell(op_stream);
800
                  if (filesize!=-1L)
801
                  {
802
                     // get back to where we were
803
                     if (0==fseek(op_stream, offset, SEEK_SET))
804
                     {
805
                        if (offset == filesize)
806
                        {
807
                           // current position is at the end of the file
808
                           // We need to append a null byte for the alignment command
809
                           DEBUG( DEBUG_OUTPUT_CMD_MASK, "ALIGNMENT (appended %d null byte(s))", padding_required );
810
 
811
                           while (padding_required--)
812
                           {
813
                              if (EOF==fputc(0, op_stream))
814
                              {
815
                                 ERROR("ALIGNMENT command failed on output file (fputc)");
816
                                 break;
817
                              }
818
                           }
819
                        }
820
                        else if (offset < filesize)
821
                        {
822
                           // current position is not at the end of the file
823
                           // We simply need to advance the position by one byte
824
                           DEBUG( DEBUG_OUTPUT_CMD_MASK, "ALIGNMENT (advanced filepos %d bytes only)", padding_required );
825
 
826
                           while (padding_required--)
827
                           {
828
                              if (0!=fseek(op_stream, 1, SEEK_CUR))
829
                              {
830
                                 ERROR("ALIGNMENT command failed on output file (fseek)");
831
                                 break;
832
                              }
833
                           }
834
                        }
835
                        else
836
                        {
837
                           ERROR("ALIGNMENT command failed on output file (offset)");
838
                        }
839
                     }
840
                     else
841
                     {
842
                        ERROR("ALIGNMENT command failed on output file (fseek)");
843
                     }
844
                  }
845
                  else
846
                  {
847
                     ERROR("ALIGNMENT command failed on output file (ftell)");
848
                  }
849
               }
850
               else
851
               {
852
                  ERROR("ALIGNMENT command failed on output file (fseek)");
853
               }
854
            }
855
            else
856
            {
857
               DEBUG( DEBUG_OUTPUT_CMD_MASK, "ALIGNMENT (no padding required)" );
858
            }
859
         }
860
         else
861
         {
862
            ERROR("Invalid alignment number in ALIGNMENT command (must be 2, 4, or 8)");
863
         }
864
      }
865
      else
866
      {
867
         ERROR("Bad/missing variable number in ALIGNMENT command");
868
      }
869
   }
870
}
871
 
872
 
873
void fn_DWTELL(char * arg_ptr)
874
{
875
   unsigned long var;
876
   int    got_a_value;
877
 
878
   (void)next_value(arg_ptr, &var, &got_a_value);
879
   if (got_a_value)
880
   {
881
      if (var >= 1 && var <= 10)
882
      {
883
         DEBUG( DEBUG_OUTPUT_CMD_MASK, "DWTELL %s (offset value:%ld)", arg_ptr, adjusted_op_stream_tell(var) );
884
 
885
         ins_word( adjusted_op_stream_tell(var) );
886
      }
887
      else
888
      {
889
         ERROR("Out of range variable number in DWTELL command (must be 1..10)");
890
      }
891
   }
892
   else
893
   {
894
      ERROR("Bad/missing variable number in DWTELL command");
895
   }
896
}
897
 
898
void fn_DLTELL(char * arg_ptr)
899
{
900
   unsigned long var;
901
   int    got_a_value;
902
 
903
   (void)next_value(arg_ptr, &var, &got_a_value);
904
   if (got_a_value)
905
   {
906
      if (var >= 1 && var <= 10)
907
      {
908
         DEBUG( DEBUG_OUTPUT_CMD_MASK, "DLTELL %s (offset value:%ld)", arg_ptr, adjusted_op_stream_tell(var) );
909
 
910
         ins_long( adjusted_op_stream_tell(var) );
911
      }
912
      else
913
      {
914
         ERROR("Out of range variable number in DLTELL command (must be 1..10)");
915
      }
916
   }
917
   else
918
   {
919
      ERROR("Bad/missing variable number in DLTELL command");
920
   }
921
}
922
 
923
 
924
void fn_DWTELLSUB(char * arg_ptr)
925
{
926
   unsigned long var1;
927
   unsigned long var2;
928
   int    got_a_value;
929
 
930
   arg_ptr = next_value(arg_ptr, &var1, &got_a_value);
931
   if (got_a_value)
932
   {
933
      if (var1 >= 1 && var1 <= 10)
934
      {
935
         arg_ptr = next_value(arg_ptr, &var2, &got_a_value);
936
         if (got_a_value)
937
         {
938
            if (var2 >= 1 && var2 <= 10)
939
            {
940
               DEBUG( DEBUG_OUTPUT_CMD_MASK, "DWTELLSUB %s (offset value:%ld)", arg_ptr, adjusted_op_stream_tell(var1) - adjusted_op_stream_tell(var2) );
941
 
942
               ins_word( adjusted_op_stream_tell(var1) - adjusted_op_stream_tell(var2) );
943
            }
944
            else
945
            {
946
               ERROR("Out of range variable number in DWTELLSUB command (must be 1..10)");
947
            }
948
         }
949
         else
950
         {
951
            ERROR("Bad/missing variable number in DWTELLSUB command");
952
         }
953
      }
954
      else
955
      {
956
         ERROR("Out of range variable number in DWTELLSUB command (must be 1..10)");
957
      }
958
   }
959
   else
960
   {
961
      ERROR("Bad/missing variable number in DWTELLSUB command");
962
   }
963
}
964
 
965
 
966
void fn_DLTELLSUB(char * arg_ptr)
967
{
968
   unsigned long var1;
969
   unsigned long var2;
970
   int    got_a_value;
971
 
972
   arg_ptr = next_value(arg_ptr, &var1, &got_a_value);
973
   if (got_a_value)
974
   {
975
      if (var1 >= 1 && var1 <= 10)
976
      {
977
         arg_ptr = next_value(arg_ptr, &var2, &got_a_value);
978
         if (got_a_value)
979
         {
980
            if (var2 >= 1 && var2 <= 10)
981
            {
982
               DEBUG( DEBUG_OUTPUT_CMD_MASK, "DLTELLSUB %s (offset value:%ld)", arg_ptr, adjusted_op_stream_tell(var1) - adjusted_op_stream_tell(var2) );
983
 
984
               ins_long( adjusted_op_stream_tell(var1) - adjusted_op_stream_tell(var2) );
985
            }
986
            else
987
            {
988
               ERROR("Out of range variable number in DLTELLSUB command (must be 1..10)");
989
            }
990
         }
991
         else
992
         {
993
            ERROR("Bad/missing variable number in DLTELLSUB command");
994
         }
995
      }
996
      else
997
      {
998
         ERROR("Out of range variable number in DLTELLSUB command (must be 1..10)");
999
      }
1000
   }
1001
   else
1002
   {
1003
      ERROR("Bad/missing variable number in DLTELLSUB command");
1004
   }
1005
}
1006
 
1007
 
1008
 
1009
 
1010
void fn_SETBASE(char * arg_ptr)
1011
{
1012
   long offset;
1013
 
1014
   offset = ftell(op_stream);
1015
   if (offset == -1L)
1016
   {
1017
      ERROR("SETBASE command failed on output file");
1018
   }
1019
   else
1020
   {
1021
      DEBUG( DEBUG_CONTROL_CMD_MASK, "SETBASE %s (base_reference:%ld)", arg_ptr, base_reference );
1022
      base_reference = offset;
1023
   }
1024
}
1025
 
1026
 
1027
/**************************************************************************/
1028
 
1029
void fn_REPEAT(char * arg_ptr)
1030
{
1031
   unsigned long count;
1032
   int got_a_value;
1033
   fpos_t stream_pos;
1034
 
1035
   (void)next_value(arg_ptr, &count, &got_a_value);
1036
   if (got_a_value)
1037
   {
1038
      if (fgetpos(cmd_stream, &stream_pos) == 0)
1039
      {
1040
         if (cmd_repeat_nest_level < (MAX_NEST_LEVEL - 1))
1041
         {
1042
            cmd_repeat_nest_level++;
1043
 
1044
            cmd_repeat_stack[cmd_repeat_nest_level].cmd_stream_pos = stream_pos;
1045
            cmd_repeat_stack[cmd_repeat_nest_level].cmd_stream_repeat = count;
1046
            cmd_repeat_stack[cmd_repeat_nest_level].cmdLineNumber = cmdLineNum;
1047
 
1048
            DEBUG( DEBUG_CONTROL_CMD_MASK, "REPEAT %s (nesting:%d, pos:%ld)", arg_ptr, cmd_repeat_nest_level, stream_pos );
1049
         }
1050
         else
1051
         {
1052
            ERROR("REPEAT command nested too deeply");
1053
         }
1054
      }
1055
      else
1056
      {
1057
         ERROR("REPEAT command failed to get current cmd file position");
1058
      }
1059
   }
1060
   else
1061
   {
1062
      ERROR("Bad/missing count value in REPEAT command");
1063
   }
1064
}
1065
 
1066
 
1067
void fn_END(char * arg_ptr)
1068
{
1069
   if (cmd_repeat_nest_level >= 0)
1070
   {
1071
      if (cmd_repeat_stack[cmd_repeat_nest_level].cmd_stream_repeat > 0)
1072
      {
1073
         cmd_repeat_stack[cmd_repeat_nest_level].cmd_stream_repeat--;
1074
 
1075
         DEBUG( DEBUG_CONTROL_CMD_MASK, "END-REPEAT (nesting:%d)", cmd_repeat_nest_level );
1076
 
1077
         if (cmd_repeat_stack[cmd_repeat_nest_level].cmd_stream_repeat > 0)
1078
         {
1079
            if (fsetpos(cmd_stream, &(cmd_repeat_stack[cmd_repeat_nest_level].cmd_stream_pos)))
1080
            {
1081
               ERROR("END could not restore cmd file position");
1082
            }
1083
            else
1084
            {
1085
               cmdLineNum = cmd_repeat_stack[cmd_repeat_nest_level].cmdLineNumber;
1086
            }
1087
         }
1088
         else
1089
         {
1090
            cmd_repeat_nest_level--;
1091
         }
1092
      }
1093
      else
1094
      {
1095
         DEBUG( DEBUG_CONTROL_CMD_MASK, "END-REPEAT (nesting:%d)", cmd_repeat_nest_level );
1096
         cmd_repeat_nest_level--;
1097
      }
1098
   }
1099
   else
1100
   {
1101
      ERROR("END could not be matched to a previous REPEAT command");
1102
   }
1103
}
1104
 
1105
/**************************************************************************/
1106
 
1107
void fn_FEEDFILE(char * arg_ptr)
1108
{
1109
   FILE * fip_stream;
1110
 
1111
   arg_ptr = skip_past_spaces(arg_ptr);
1112
 
1113
   if( (fip_stream = fopen( arg_ptr, "rb" )) != NULL )
1114
   {
1115
      int c;
1116
 
1117
      DEBUG( DEBUG_OUTPUT_CMD_MASK, "FEEDFILE %s", arg_ptr );
1118
 
1119
      c = fgetc(fip_stream);
1120
      while (c != EOF)
1121
      {
1122
         fputc(c, op_stream);
1123
         c = fgetc(fip_stream);
1124
      }
1125
 
1126
      fclose(fip_stream);
1127
 
1128
   }
1129
   else
1130
   {
1131
      ERROR("Could not open file");
1132
   }
1133
}
1134
 
1135
/**************************************************************************/
1136
 
1137
void fn_NAMEVAR(char * arg_ptr)
1138
{
1139
   char * initial_arg_ptr = arg_ptr;
1140
 
1141
   unsigned long variantType;
1142
   unsigned long dataSize;
1143
   int got_a_value;
1144
 
1145
   arg_ptr = next_value(arg_ptr, &variantType, &got_a_value);
1146
   if (got_a_value)
1147
   {
1148
      while ( (*arg_ptr != ',') )
1149
         arg_ptr++;
1150
 
1151
      if (*arg_ptr == ',')
1152
         arg_ptr++;
1153
 
1154
      arg_ptr = skip_past_spaces(arg_ptr);
1155
 
1156
 
1157
      // put the representation type
1158
      variantType = (0x1000 + variantType) & 0xFFFF;
1159
 
1160
      dataSize = strlen(arg_ptr);
1161
      dataSize++;                   // Account for null trerminator
1162
      if (dataSize & 1)             // Do alignment
1163
         dataSize++;
1164
 
1165
      DEBUG( DEBUG_OUTPUT_CMD_MASK, "NAMEVAR %s (variantType:%d, dataSize:%d)", initial_arg_ptr, variantType, dataSize );
1166
 
1167
      ins_word(variantType);
1168
 
1169
      ins_word(dataSize);
1170
 
1171
      // put the text
1172
      while (*arg_ptr != 0)
1173
         fputc(*arg_ptr++, op_stream);
1174
 
1175
      fputc(0, op_stream); // put null terminator
1176
 
1177
      fn_ALIGNMENT(arg_ptr, 2);   // do alignment
1178
   }
1179
   else
1180
   {
1181
      ERROR("Bad/missing variantType value in NAMEVAR command");
1182
   }
1183
}
1184
 
1185
/**************************************************************************/
1186
 
1187
void fn_GOSUB(char * arg_ptr)
1188
{
1189
   char * initial_arg_ptr = arg_ptr;
1190
 
1191
   // Read subroutine name
1192
   static char subname[256];
1193
   static char *subnameptr = &subname[0];
1194
   static int subnamelen = 0;
1195
   static fpos_t subposition;
1196
 
1197
   int found = 0;
1198
 
1199
   *subnameptr = 0;
1200
 
1201
   if (*arg_ptr != 0)
1202
   {
1203
      if (stackptr < (MAX_STACK-1))
1204
      {
1205
         fpos_t fposition;
1206
 
1207
         if (fgetpos(cmd_stream, &fposition) == 0)
1208
         {
1209
            if (strlen(arg_ptr) > 250)
1210
            {
1211
               ERROR("GOSUB subroutine name too long");
1212
            }
1213
            else
1214
            {
1215
               // Get subname, subnameptr, subnamelen
1216
               subnameptr = &subname[0];
1217
               while (*arg_ptr != 0)
1218
                  *subnameptr++ = *arg_ptr++;
1219
               *subnameptr = 0;
1220
 
1221
               subnamelen = strlen(subname);
1222
               if (subnamelen == 0)
1223
               {
1224
                  ERROR("GOSUB subroutine name missing");
1225
               }
1226
               else
1227
               {
1228
                  // scan cmd file from the beginning, for the subroutine of the required name
1229
                  if (0==fseek(cmd_stream, 0, SEEK_SET))
1230
                  {
1231
                     char * cmd_args;
1232
                     long tempCmdLineNum = 1;
1233
 
1234
                     fgets_and_strip_newline( cmd_line, MAX_LINE_LEN, cmd_stream );
1235
                     do {
1236
                        cmd_args = skip_to_spaces(cmd_line);
1237
                        cmd_args = skip_past_spaces(cmd_args);
1238
 
1239
                        if (strnicmp(cmd_line, "SUB", 3) == 0) {
1240
                           if (strnicmp(subname, cmd_args, subnamelen) == 0) {
1241
                              // capture cmd file position where the subroutine begins
1242
                              if (fgetpos(cmd_stream, &subposition) == 0) {
1243
                                 stackptr++;
1244
                                 stack[stackptr].filepos = fposition;
1245
                                 stack[stackptr].cmdLineNumber = cmdLineNum;
1246
                                 DEBUG( DEBUG_CONTROL_CMD_MASK, "GOSUB %s", subname );
1247
                                 cmdLineNum = tempCmdLineNum;
1248
                                 found = 1;
1249
                                 break;
1250
                              }
1251
                              else {
1252
                                 ERROR("GOSUB failed to get cmd stream subroutine filepos");
1253
                              }
1254
                           }
1255
                        }
1256
 
1257
                        tempCmdLineNum++;
1258
 
1259
                     } while (fgets_and_strip_newline( cmd_line, MAX_LINE_LEN, cmd_stream ) != NULL);
1260
 
1261
                     if (!found)
1262
                     {
1263
                        ERROR("GOSUB could not find subroutine");
1264
                     }
1265
                  }
1266
                  else
1267
                  {
1268
                     ERROR("GOSUB failed to seek to beginning of cmd file");
1269
                  }
1270
               }
1271
            }
1272
         }
1273
         else
1274
         {
1275
            ERROR("GOSUB failed to get cmd stream calling filepos");
1276
         }
1277
      }
1278
      else
1279
      {
1280
         ERROR("GOSUB out of stack space");
1281
      }
1282
   }
1283
}
1284
 
1285
/**************************************************************************/
1286
 
1287
void fn_MSG(char * arg_ptr)
1288
{
1289
   if (*arg_ptr != 0)
1290
   {
1291
      printf( arg_ptr );
1292
   }
1293
}
1294
 
1295
/**************************************************************************/
1296
 
1297
void fn_OUTPUT_FILE(char * arg_ptr)
1298
{
1299
   char filename[1024];
1300
   char * pFilename = filename;
1301
 
1302
   if (*arg_ptr != 0)
1303
   {
1304
      while (*arg_ptr != 0)
1305
      {
1306
         *pFilename++ = *arg_ptr++;
1307
      }
1308
      *pFilename = 0;
1309
 
1310
      if (i_op_file_opened)
1311
      {
1312
         i_op_file_opened = FALSE;
1313
         fclose(op_stream);
1314
      }
1315
 
1316
      if( (op_stream = fopen( filename, "wb" )) == NULL )
1317
      {
1318
         char buff[2048];
1319
         sprintf(buff, "Could not open output file %s", filename );
1320
         ERROR( buff );
1321
      }
1322
      else
1323
      {
1324
         i_op_file_opened = TRUE;
1325
         DEBUG( DEBUG_OUTPUT_CMD_MASK, "OUTPUT_FILE %s", filename );
1326
      }
1327
   }
1328
   else
1329
   {
1330
      ERROR("Missing filename from OUTPUT_FILE command");
1331
   }
1332
 
1333
}
1334
 
1335
/**************************************************************************/
1336
 
1337
int InputFileOpen(void)
1338
{
1339
   if (!i_ip_file_opened)
1340
   {
1341
      ERROR("No binary input file has been specified");
1342
      return FALSE;
1343
   }
1344
   else
1345
   {
1346
      return TRUE;
1347
   }
1348
}
1349
 
1350
 
1351
int OutputFileOpen(void)
1352
{
1353
   if (!i_op_file_opened)
1354
   {
1355
      ERROR("No binary output file has been specified");
1356
      return FALSE;
1357
   }
1358
   else
1359
   {
1360
      return TRUE;
1361
   }
1362
}
1363
 
1364
/**************************************************************************/
1365
 
1366
void do_binflow_processing(void)
1367
{
1368
   char * cmd_args;
1369
 
1370
   if (fgets_and_strip_newline( cmd_line, MAX_LINE_LEN, cmd_stream ) == NULL)
1371
   {
1372
      printf("ERROR : Command File is empty\n");
1373
      return;
1374
   }
1375
   else
1376
   {
1377
      do
1378
      {
1379
         cmdLineNum++;
1380
 
1381
         if (cmd_line[0] != 0)
1382
         {
1383
            cmd_args = skip_to_spaces(cmd_line);
1384
            cmd_args = skip_past_spaces(cmd_args);
1385
 
1386
            if (skippingPastSub)
1387
            {
1388
               if (strnicmp(cmd_line, "SUB", 3) == 0) {
1389
                  ERROR("SUBROUTINE definition nesting is prohibited");
1390
               }
1391
               else if (strnicmp(cmd_line, "ENDSUB", 6) == 0) {
1392
                  skippingPastSub = 0;
1393
               }
1394
            }
1395
            else if (strnicmp(cmd_line, "LITTLE_ENDIAN", 13) == 0) {
1396
               endianism = LITTLE_ENDIAN;
1397
            }
1398
            else if (strnicmp(cmd_line, "BIG_ENDIAN", 10) == 0) {
1399
               endianism = BIG_ENDIAN;
1400
            }
1401
            else if (strnicmp(cmd_line, "OUTPUT_FILE", 11) == 0) {
1402
               strip_trailing_comment_and_spaces( cmd_line );
1403
               fn_OUTPUT_FILE(cmd_args);
1404
            }
1405
            else if (strnicmp(cmd_line, "BREAKPOINT", 10) == 0) {
1406
               _CrtDbgBreak();
1407
            }
1408
            else if (strnicmp(cmd_line, "SEEKSTART", 9) == 0) {
1409
               strip_trailing_comment_and_spaces( cmd_line );
1410
               if (OutputFileOpen())
1411
                  fn_SEEKSTART(cmd_args);
1412
            }
1413
            else if (strnicmp(cmd_line, "DWTELLSUB", 9) == 0) {
1414
               strip_trailing_comment_and_spaces( cmd_line );
1415
               if (OutputFileOpen())
1416
                  fn_DWTELLSUB(cmd_args);
1417
            }
1418
            else if (strnicmp(cmd_line, "DLTELLSUB", 9) == 0) {
1419
               strip_trailing_comment_and_spaces( cmd_line );
1420
               if (OutputFileOpen())
1421
                  fn_DLTELLSUB(cmd_args);
1422
            }
1423
            else if (strnicmp(cmd_line, "ALIGNMENT", 9) == 0) {
1424
               strip_trailing_comment_and_spaces( cmd_line );
1425
               if (OutputFileOpen())
1426
                  fn_ALIGNMENT(cmd_args, 0);
1427
            }
1428
            else if (strnicmp(cmd_line, "SEEKTELL", 8) == 0) {
1429
               strip_trailing_comment_and_spaces( cmd_line );
1430
               if (OutputFileOpen())
1431
                  fn_SEEKTELL(cmd_args);
1432
            }
1433
            else if (strnicmp(cmd_line, "FEEDFILE", 8) == 0) {
1434
               strip_trailing_comment_and_spaces( cmd_line );
1435
               if (OutputFileOpen())
1436
                  fn_FEEDFILE(cmd_args);
1437
            }
1438
            else if (strnicmp(cmd_line, "SEEKEND", 7) == 0) {
1439
               strip_trailing_comment_and_spaces( cmd_line );
1440
               if (OutputFileOpen())
1441
                  fn_SEEKEND(cmd_args);
1442
            }
1443
            else if (strnicmp(cmd_line, "SEEKCUR", 7) == 0) {
1444
               strip_trailing_comment_and_spaces( cmd_line );
1445
               if (OutputFileOpen())
1446
                  fn_SEEKCUR(cmd_args);
1447
            }
1448
            else if (strnicmp(cmd_line, "NAMEVAR", 7) == 0) {
1449
               strip_trailing_comment_and_spaces( cmd_line );
1450
               if (OutputFileOpen())
1451
                  fn_NAMEVAR(cmd_args);
1452
            }
1453
            else if (strnicmp(cmd_line, "SETBASE", 7) == 0) {
1454
               strip_trailing_comment_and_spaces( cmd_line );
1455
               if (OutputFileOpen())
1456
                  fn_SETBASE(cmd_args);
1457
            }
1458
            else if (strnicmp(cmd_line, "ENDSUB", 6) == 0) {
1459
               if (stackptr > -1) {
1460
                  if (fsetpos(cmd_stream, &stack[stackptr].filepos))  {
1461
                     ERROR("ENDSUB failed to return to calling point");
1462
                  }
1463
                  else {
1464
                     DEBUG( DEBUG_CONTROL_CMD_MASK, "ENDSUB" );
1465
                     cmdLineNum = stack[stackptr].cmdLineNumber;
1466
                     stackptr--;
1467
                  }
1468
               }
1469
               else {
1470
                  ERROR("ENDSUB unexpected at this time");
1471
               }
1472
            }
1473
            else if (strnicmp(cmd_line, "REWIND", 6) == 0) {
1474
               strip_trailing_comment_and_spaces( cmd_line );
1475
               if (InputFileOpen())
1476
                  fn_REWIND(cmd_args);
1477
            }
1478
            else if (strnicmp(cmd_line, "REPEAT", 6) == 0) {
1479
               strip_trailing_comment_and_spaces( cmd_line );
1480
               fn_REPEAT(cmd_args);
1481
            }
1482
            else if (strnicmp(cmd_line, "DWTELL", 6) == 0) {
1483
               strip_trailing_comment_and_spaces( cmd_line );
1484
               if (OutputFileOpen())
1485
                  fn_DWTELL(cmd_args);
1486
            }
1487
            else if (strnicmp(cmd_line, "DLTELL", 6) == 0) {
1488
               strip_trailing_comment_and_spaces( cmd_line );
1489
               if (OutputFileOpen())
1490
                  fn_DLTELL(cmd_args);
1491
            }
1492
            else if (strnicmp(cmd_line, "DEBUG", 5) == 0) {
1493
               strip_trailing_comment_and_spaces( cmd_line );
1494
               fn_DEBUG(cmd_args);
1495
            }
1496
            else if (strnicmp(cmd_line, "NTEXT", 5) == 0) {
1497
               strip_trailing_comment( cmd_line );
1498
               if (OutputFileOpen())
1499
                  fn_NTEXT(cmd_args);
1500
            }
1026 dpurdie 1501
            else if (strnicmp(cmd_line, "ZTEXT", 5) == 0) {
1502
               strip_trailing_comment( cmd_line );
1503
               if (OutputFileOpen())
1504
                  fn_ZTEXT(cmd_args);
1505
            }
1024 ghuddy 1506
            else if (strnicmp(cmd_line, "ALIGN", 5) == 0) {
1507
               strip_trailing_comment_and_spaces( cmd_line );
1508
               if (OutputFileOpen())
1509
                  fn_ALIGNMENT(cmd_args, 2);
1510
            }
1511
            else if (strnicmp(cmd_line, "GOSUB", 5) == 0) {
1512
               strip_trailing_comment_and_spaces( cmd_line );
1513
               fn_GOSUB(cmd_args);
1514
            }
1515
            else if (strnicmp(cmd_line, "FEED", 4) == 0) {
1516
               strip_trailing_comment_and_spaces( cmd_line );
1517
               if (OutputFileOpen() && InputFileOpen())
1518
                  fn_FEED(cmd_args);
1519
            }
1520
            else if (strnicmp(cmd_line, "SKIP", 4) == 0) {
1521
               strip_trailing_comment_and_spaces( cmd_line );
1522
               if (InputFileOpen())
1523
                  fn_SKIP(cmd_args);
1524
            }
1525
            else if (strnicmp(cmd_line, "TEXT", 4) == 0) {
1526
               strip_trailing_comment( cmd_line );
1527
               if (OutputFileOpen())
1528
                  fn_TEXT(cmd_args);
1529
            }
1530
            else if (strnicmp(cmd_line, "MARK", 4) == 0) {
1531
               strip_trailing_comment_and_spaces( cmd_line );
1532
               if (InputFileOpen())
1533
                  fn_MARK(cmd_args);
1534
            }
1535
            else if (strnicmp(cmd_line, "TELL", 4) == 0) {
1536
               strip_trailing_comment_and_spaces( cmd_line );
1537
               if (OutputFileOpen())
1538
                  fn_TELL(cmd_args);
1539
            }
1540
            else if (strnicmp(cmd_line, "DUP", 3) == 0) {
1541
               strip_trailing_comment_and_spaces( cmd_line );
1542
               if (OutputFileOpen())
1543
                  fn_DUP(cmd_args);
1544
            }
1545
            else if (strnicmp(cmd_line, "END", 3) == 0) {
1546
               strip_trailing_comment_and_spaces( cmd_line );
1547
               fn_END(cmd_args);
1548
            }
1549
            else if (strnicmp(cmd_line, "MSG", 3) == 0) {
1550
               strip_trailing_comment_and_spaces( cmd_line );
1551
               fn_MSG(cmd_args);
1552
            }
1553
            else if (strnicmp(cmd_line, "SUB", 3) == 0) {
1554
               if (stackptr > -1) {
1555
                  ERROR("SUBROUTINE definition nesting is prohibited");
1556
               }
1557
               else {
1558
                  skippingPastSub = 1;
1559
               }
1560
            }
1561
            else if (strnicmp(cmd_line, "DB", 2) == 0) {
1562
               strip_trailing_comment_and_spaces( cmd_line );
1563
               if (OutputFileOpen())
1564
                  fn_DB(cmd_args);
1565
            }
1566
            else if (strnicmp(cmd_line, "DW", 2) == 0) {
1567
               strip_trailing_comment_and_spaces( cmd_line );
1568
               if (OutputFileOpen())
1569
                  fn_DW(cmd_args);
1570
            }
1571
            else if (strnicmp(cmd_line, "DL", 2) == 0) {
1572
               strip_trailing_comment_and_spaces( cmd_line );
1573
               if (OutputFileOpen())
1574
                  fn_DL(cmd_args);
1575
            }
1028 dpurdie 1576
            else if (strnicmp(cmd_line, "DQ", 2) == 0) {
1577
               strip_trailing_comment_and_spaces( cmd_line );
1578
               if (OutputFileOpen())
1579
                  fn_DQ(cmd_args);
1580
            }
1581
 
1024 ghuddy 1582
            else {
1583
               if (  ( cmd_line[0] != ' '  )
1584
                  && ( cmd_line[0] != 0    )
1585
                  && ( cmd_line[0] != '\n' )
1586
                  && ( cmd_line[0] != '#'  ) )
1587
               {
1588
                  printf("ERROR on line %u of command file\n\n", cmdLineNum);
1589
                  printf("  %s\n", cmd_line);
1590
                  printf("  ^\n");
1591
                  printf("  |\n");
1592
                  printf("  | Unknown Command\n");
1026 dpurdie 1593
                  mustAbort = 1;
1024 ghuddy 1594
                  break;
1595
               }
1596
            }
1597
         }
1598
 
1599
 
1600
         if (mustAbort)
1601
            break;
1602
 
1603
      } while (fgets_and_strip_newline( cmd_line, MAX_LINE_LEN, cmd_stream ) != NULL);
1604
   }
1605
}
1606
 
1607
 
1608
/**************************************************************************/
1609
 
1610
void newline(void)
1611
{
1612
   printf("\n");
1613
}
1614
 
1615
void header(void)
1616
{
1617
   newline();
1618
   printf("%s, by Gordon Huddy, %s\n", BUILDNAME, BUILDDATE);
1619
   newline();
1620
}
1621
 
1622
void commands(void)
1623
{
1624
   header();
1625
 
1626
   printf("Processor commands:-\n");
1627
 
1628
   newline();
1629
 
1630
   printf("  COMMAND FILE COMMANDS --------------------------------------------------------------------------\n\n");
1631
   printf("  #                      'Start of comment' marker in command file\n");
1632
   printf("  REPEAT n               Specify a command block to be repeated n times\n");
1633
   printf("  END                    Marks the end of a repeated command block\n");
1634
   printf("  DEBUG mask             Turns on debug\n");
1635
   printf("                         Masks: 1 = Command File Control commands\n");
1636
   printf("                                2 = Output Binary File commands\n");
1637
   printf("                                4 = Input Binary File commands\n");
1638
   printf("  MSG text               Sends the message text to stdout\n");
1639
   newline();
1640
   printf("  NB. REPEAT-END commands can be nested (Max Level %d)\n", MAX_NEST_LEVEL);
1641
   newline();
1642
 
1643
   printf("  OUTPUT BINARY FILE COMMANDS---------------------------------------------------------------------\n\n");
1644
   printf("  DUP  n,v               Add the 8-bit value v to the output file, n times\n");
1645
   printf("  DB v,v,..,v            Add the specified list of  8-bit values to the output file\n");
1646
   printf("  DW v,v,..,v            Add the specified list of 16-bit values to the output file\n");
1647
   printf("  DL v,v,..,v            Add the specified list of 32-bit values to the output file\n");
1028 dpurdie 1648
   printf("  DQ v,v,..,v            Add the specified list of 64-bit values to the output file\n");
1024 ghuddy 1649
   printf("  TEXT text              Add the specified text to the output file\n");
1650
   printf("  NTEXT v,text           Add exactly v characters of the specified text to the output file\n");
1651
   printf("                           - pad output file with 0's if insufficient text provided\n");
1026 dpurdie 1652
   printf("  ZTEXT v,text           Add exactly v-1 characters and a NULL terminator of the specified text to the output file\n");
1024 ghuddy 1653
   printf("  BIG_ENDIAN             Turn Big-endian on (default behaviour)\n");
1654
   printf("  LITTLE_ENDIAN          Turn Big-endian off\n");
1655
   printf("  OUTPUT_FILE name       Opens a new Output File, closing the previous one\n");
1656
   printf("  SEEKSTART offset       Seeks to the specified offset from the start of the output file\n");
1657
   printf("  SEEKEND offset         Seeks to the specified offset from the end of the output file\n");
1658
   printf("  SEEKCUR offset         Seeks to the specified offset from the current position in the output file\n");
1659
   printf("  TELL var               Saves current position in the output file to internal variable 1..10\n");
1660
   printf("  SEEKTELL var           Using internal variable 1..10, seeks to the saved position in the output file\n");
1661
   printf("  DWTELL var             Using internal variable 1..10, adds the saved position as a 16-bit value to the output file\n");
1662
   printf("  DLTELL var             Using internal variable 1..10, adds the saved position as a 32-bit value to the output file\n");
1663
   printf("  DWTELLSUB var1, var2   Using internal variables 1..10, adds the difference between saved positions (var1 - var2)\n");
1664
   printf("                         as a 16-bit value to the output file\n");
1665
   printf("  DLTELLSUB var1, var2   Using internal variables 1..10, adds the difference between saved positions (var1 - var2)\n");
1666
   printf("                         as a 32-bit value to the output file\n");
1667
   printf("  SETBASE                Sets the base reference from which offsets in internal variables 1..10 are measured,\n");
1668
   printf("                         to the current output file position (default = beginning of output file)\n");
1669
   printf("                         SETBASE only affects the values DLTELL and DWTELL write.\n");
1670
   printf("  ALIGN                  If current file position is odd, advances it by 1 byte (equivalent to 'ALIGNMENT 2' command)\n");
1671
   printf("  ALIGNMENT v            Performs specified alignment - v must be 2, 4, or 8\n");
1672
   printf("  NAMEVAR vt,text        Add the specified name variant type to the output file\n");
1673
   printf("  SUB name               Begin Defining a subroutine\n");
1674
   printf("  ENDSUB                 End the definition of a subroutine\n");
1675
   printf("  GOSUB name             Call a subroutine\n");
1676
   printf("  FEEDFILE filename      Feed the entire contents of the file with the given name to the output file\n");
1677
   newline();
1678
 
1679
   printf("  INPUT BINARY FILE COMMANDS---------------------------------------------------------------------\n\n");
1680
   printf("  FEED n                 Feed n bytes from the input file to the output file\n");
1681
   printf("  SKIP n                 Skip n bytes of the input file\n");
1682
   printf("  MARK                   'Marks' current position in input file\n");
1683
   printf("  REWIND                 Return to 'Marked' position in input file\n");
1684
   newline();
1685
}
1686
 
1687
 
1688
 
1689
void usage(void)
1690
{
1691
   header();
1692
 
1693
   printf("BINFLOW /c=cmdfile [/o=outfile] [/i=infile] [/d=mask] \n");
1694
 
1695
   newline();
1696
 
1697
   printf("  /c=cmdfile : Compulsory - contains your processor command script.\n");
1698
   printf("  /o=outfile : Optional - Specifies an output file. This switch can be\n");
1699
   printf("               omitted if the cmdfile itself specifies one or more output files.\n");
1700
   printf("  /i=infile  : Optional - Specifies a binary input file containing some data that must find\n");
1701
   printf("               its way through to the outfile under control of the script commands given in\n");
1702
   printf("               the cmdfile.\n");
1703
   printf("  /d=mask    : Optional - Identical to the operation of the DEBUG command inside a cmdfile\n");
1704
 
1705
   newline();
1706
 
1707
   printf("  This program enables you to produce a binary file from a command file\n");
1708
   printf("  description using simple commands. Some commands allow data from a source\n");
1709
   printf("  binary file to be passed to the output file also. The command file\n");
1710
   printf("  is processed sequentially.\n");
1711
 
1712
   newline();
1713
 
1714
   printf("  Type BINFLOW ? for a summary of commands available\n");
1715
 
1716
   newline();
1717
}
1718
 
1719
 
1026 dpurdie 1720
int main( int argc,        /* Number of strings in array argv          */
1024 ghuddy 1721
          char *argv[],    /* Array of command-line argument strings   */
1722
          char **envp )    /* Array of environment variable strings    */
1723
{
1724
   char * pCmdFilename = NULL;
1725
   char * pOutputFilename = NULL;
1726
   char * pInputFilename = NULL;
1727
   int showUsage = FALSE;
1728
   int showCommands = FALSE;
1729
 
1730
   int argi = 1;
1731
 
1732
   if (argi == argc)
1733
   {
1734
      showUsage = TRUE;
1735
      goto binflow_exit;
1736
   }
1737
 
1738
   while (argi < argc)
1739
   {
1740
      char * pArg = argv[argi];
1741
      if (pArg[0] == '/' || pArg[0] == '\\')
1742
      {
1743
         if ( strlen(pArg) > 3 )
1744
         {
1745
            switch(pArg[1])
1746
            {
1747
            case 'c' :
1748
               pCmdFilename = &pArg[3];
1749
               break;
1750
 
1751
            case 'i' :
1752
               pInputFilename = &pArg[3];
1753
               break;
1754
 
1755
            case 'o':
1756
               pOutputFilename = &pArg[3];
1757
               break;
1758
 
1759
            case 'd':
1760
               fn_DEBUG(pArg);
1761
               break;
1762
 
1763
            default:
1764
               printf("ERROR : Unrecognized command line switch (%s)\n", pArg );
1765
               showUsage = TRUE;
1766
               goto binflow_exit;
1767
               break;
1768
            }
1769
 
1770
         }
1771
         else
1772
         {
1773
            printf("ERROR : Command line switch appears incomplete or malformed (%s)\n", pArg );
1774
            showUsage = TRUE;
1775
            goto binflow_exit;
1776
         }
1777
      }
1778
      else if (pArg[0] == '?' )
1779
      {
1780
         showCommands = TRUE;
1781
         goto binflow_exit;
1782
      }
1783
      else
1784
      {
1785
         printf("ERROR : Unrecognized command line switch (%s)\n", pArg );
1786
         showUsage = TRUE;
1787
         goto binflow_exit;
1788
      }
1789
 
1790
      argi++;
1791
   }
1792
 
1793
 
1794
   if (pCmdFilename)
1795
   {
1796
      if( (cmd_stream = fopen( pCmdFilename, "r" )) == NULL )
1797
      {
1798
         printf("ERROR : Could not open command file\n");
1799
         goto binflow_exit;
1800
      }
1801
   }
1802
   else
1803
   {
1804
      printf("ERROR : A command file must be specified\n");
1805
      showUsage = TRUE;
1806
      goto binflow_exit;
1807
   }
1808
 
1809
   if (pOutputFilename)
1810
   {
1811
      if( (op_stream = fopen( pOutputFilename, "wb" )) == NULL )
1812
      {
1813
         fclose(cmd_stream);
1814
         printf("ERROR : Could not open output file\n");
1026 dpurdie 1815
         mustAbort = 1;
1024 ghuddy 1816
         goto binflow_exit;
1817
      }
1818
      else
1819
      {
1820
         i_op_file_opened = TRUE;
1821
      }
1822
   }
1823
 
1824
   if (pInputFilename)
1825
   {
1826
      if( (ip_stream = fopen( pInputFilename, "rb" )) == NULL )
1827
      {
1828
         fclose(cmd_stream);
1829
         if (pOutputFilename)
1830
            fclose(op_stream);
1831
         printf("ERROR : Could not open binary input file\n");
1832
         goto binflow_exit;
1833
      }
1834
      else
1835
      {
1836
         i_ip_file_opened = TRUE;
1837
      }
1838
   }
1839
 
1840
   do_binflow_processing();
1841
 
1842
   fclose(op_stream);
1843
   fclose(cmd_stream);
1844
 
1845
   if (i_ip_file_opened)
1846
      fclose(ip_stream);
1847
 
1848
   if (i_had_input_stream_errors)
1026 dpurdie 1849
   {
1024 ghuddy 1850
      printf("ERROR : Errors occurred when reading your input data file\n");
1026 dpurdie 1851
      mustAbort = 1;
1852
   }
1024 ghuddy 1853
 
1026 dpurdie 1854
   if (mustAbort)
1855
   {
1856
        exitCode = 1;
1857
        if ( pOutputFilename )
1858
            unlink (pOutputFilename);
1859
   }
1860
   return exitCode;
1861
 
1862
 
1024 ghuddy 1863
binflow_exit:
1026 dpurdie 1864
   exitCode = 2;
1024 ghuddy 1865
   if (showUsage)
1866
   {
1867
      usage();
1868
   }
1869
   else if (showCommands)
1870
   {
1871
      commands();
1872
   }
1026 dpurdie 1873
 
1874
   return exitCode;
1024 ghuddy 1875
}
1876
 
1877
 
1878
 
1879
/************************************************************************************************************/
1880
/** ENDIAN CONVERSION FUNCTIONS *****************************************************************************/
1881
/************************************************************************************************************/
1882
 
1883
void ins_byte(unsigned long value)
1884
{
1885
   fputc(value & 255, op_stream);
1886
}
1887
 
1888
 
1889
void ins_word(unsigned long value)
1890
{
1891
   if (endianism == BIG_ENDIAN)
1892
   {
1893
      fputc((value >> 8) & 255, op_stream);
1894
      fputc(value & 255, op_stream);
1895
   }
1896
   else
1897
   {
1898
      fputc(value & 255, op_stream);
1899
      fputc((value >> 8) & 255, op_stream);
1900
   }
1901
}
1902
 
1903
 
1904
void ins_long(unsigned long value)
1905
{
1906
   if (endianism == BIG_ENDIAN)
1907
   {
1908
      fputc((value >> 24) & 255, op_stream);
1909
      fputc((value >> 16) & 255, op_stream);
1910
      fputc((value >> 8 ) & 255, op_stream);
1911
      fputc(value & 255, op_stream);
1912
   }
1913
   else
1914
   {
1915
      fputc(value & 255, op_stream);
1916
      fputc((value >> 8 ) & 255, op_stream);
1917
      fputc((value >> 16) & 255, op_stream);
1918
      fputc((value >> 24) & 255, op_stream);
1919
   }
1920
}
1921
 
1028 dpurdie 1922
void ins_quad(unsigned __int64 value)
1923
{
1924
   if (endianism == BIG_ENDIAN)
1925
   {
1926
      fputc((int)(value >> 7*8) & 255, op_stream);
1927
      fputc((int)(value >> 6*8) & 255, op_stream);
1928
      fputc((int)(value >> 5*8) & 255, op_stream);
1929
      fputc((int)(value >> 4*8) & 255, op_stream);
1930
      fputc((int)(value >> 3*8) & 255, op_stream);
1931
      fputc((int)(value >> 2*8) & 255, op_stream);
1932
      fputc((int)(value >> 1*8) & 255, op_stream);
1933
      fputc((int)(value)        & 255, op_stream);
1934
   }
1935
   else
1936
   {
1937
      fputc((int)value          & 255, op_stream);
1938
      fputc((int)(value >> 1*8 )& 255, op_stream);
1939
      fputc((int)(value >> 2*8) & 255, op_stream);
1940
      fputc((int)(value >> 3*8) & 255, op_stream);
1941
      fputc((int)(value >> 4*8) & 255, op_stream);
1942
      fputc((int)(value >> 5*8) & 255, op_stream);
1943
      fputc((int)(value >> 6*8) & 255, op_stream);
1944
      fputc((int)(value >> 7*8) & 255, op_stream);
1945
   }
1946
}
1024 ghuddy 1947
 
1948
 
1028 dpurdie 1949
 
1950
 
1024 ghuddy 1951
/* END OF File */