Subversion Repositories DevTools

Rev

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