Subversion Repositories DevTools

Rev

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