Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
2
#include "stdinc.h"
3
#include "nlmessages.h"
4
#include "stringlists.h"
5
#include "codechunks.h"
6
#include "entryaddress.h"
7
#include "invaddress.h"
8
#include "strutil.h"
9
#include "cmdarg.h"
10
#include "msg_level.h"
11
#include "dasmdef.h"
12
#include "cpulist.h"
13
#include "console.h"
14
#include "nls.h"
15
#include "version.h"
16
#include "das.rsc"
17
 
18
#include "deco68.h"
19
#include "deco87c800.h"
20
#include "deco4004.h"
21
 
22
#define TABSIZE 8
23
 
24
char *pEnvName = "DASCMD";
25
 
26
void WrCopyRight(const char *Msg)
27
{
28
  printf("%s\n%s\n", Msg, InfoMessCopyright);
29
}
30
 
31
typedef void (*tChunkCallback)(const OneChunk *pChunk, Boolean IsData, void *pUser);
32
 
33
static void IterateChunks(tChunkCallback Callback, void *pUser)
34
{
35
  Word NextCodeChunk, NextDataChunk;
36
  const OneChunk *pChunk;
37
  Boolean IsData;
38
 
39
  NextCodeChunk = NextDataChunk = 0;
40
  while ((NextCodeChunk < UsedCodeChunks.RealLen) || (NextDataChunk < UsedDataChunks.RealLen))
41
  {
42
    if (NextCodeChunk >= UsedCodeChunks.RealLen)
43
    {
44
      pChunk = UsedDataChunks.Chunks + (NextDataChunk++);
45
      IsData = True;
46
    }
47
    else if (NextDataChunk >= UsedDataChunks.RealLen)
48
    {
49
      pChunk = UsedCodeChunks.Chunks + (NextCodeChunk++);
50
      IsData = False;
51
    }
52
    else if (UsedDataChunks.Chunks[NextDataChunk].Start < UsedCodeChunks.Chunks[NextCodeChunk].Start)
53
    {
54
      pChunk = UsedDataChunks.Chunks + (NextDataChunk++);
55
      IsData = True;
56
    }
57
    else
58
    {
59
      pChunk = UsedCodeChunks.Chunks + (NextCodeChunk++);
60
      IsData = False;
61
    }
62
 
63
    Callback(pChunk, IsData, pUser);
64
  }
65
}
66
 
67
typedef struct
68
{
69
  FILE *pDestFile;
70
  LargeWord Sum;
71
} tDumpIteratorData;
72
 
73
static void DumpIterator(const OneChunk *pChunk, Boolean IsData, void *pUser)
74
{
75
  String Str;
76
  tDumpIteratorData *pData = (tDumpIteratorData*)pUser;
77
 
78
  HexString(Str, sizeof(Str), pChunk->Start, 0);
79
  fprintf(pData->pDestFile, "\t\t; %s...", Str);
80
  HexString(Str, sizeof(Str), pChunk->Start + pChunk->Length - 1, 0);
81
  fprintf(pData->pDestFile, "%s (%s)\n", Str, IsData ? "data" :"code");
82
  pData->Sum += pChunk->Length;
83
}
84
 
85
static void DumpChunks(const ChunkList *NChunk, FILE *pDestFile)
86
{
87
  tDumpIteratorData Data;
88
  String Str;
89
 
90
  UNUSED(NChunk);
91
 
92
  Data.pDestFile = pDestFile;
93
  Data.Sum = 0;
94
  fprintf(pDestFile, "\t\t; disassembled area:\n");
95
  IterateChunks(DumpIterator, &Data);
96
  as_snprintf(Str, sizeof(Str), "\t\t; %lllu/%lllu bytes disassembled", Data.Sum, GetCodeChunksStored(&CodeChunks));
97
  fprintf(pDestFile, "%s\n", Str);
98
}
99
 
100
static int tabbedstrlen(const char *s)
101
{
102
  int Result = 0;
103
 
104
  for (; *s; s++)
105
  {
106
    if (*s == '\t')
107
      Result += TABSIZE - (Result % TABSIZE);
108
    else
109
      Result++;
110
  }
111
  return Result;
112
}
113
 
114
static void PrTabs(FILE *pDestFile, int TargetLen, int ThisLen)
115
{
116
  while (ThisLen < TargetLen)
117
  {
118
    fputc('\t', pDestFile);
119
    ThisLen += TABSIZE - (ThisLen % TABSIZE);
120
  }
121
}
122
 
123
static as_cmd_result_t ArgError(int MsgNum, const char *pArg)
124
{
125
  if (pArg)
126
    fprintf(stderr, "%s:", pArg);
127
  fprintf(stderr, "%s\n", getmessage(MsgNum));
128
 
129
  return e_cmd_err;
130
}
131
 
132
static as_cmd_result_t CMD_BinFile(Boolean Negate, const char *pArg)
133
{
134
  LargeWord Start = 0, Len = 0, Gran = 1;
135
  char *pStart = NULL, *pLen = NULL, *pGran = NULL;
136
  String Arg;
137
  Boolean OK;
138
  tCodeChunk Chunk;
139
 
140
  if (Negate || !*pArg)
141
    return ArgError(Num_ErrMsgFileArgumentMissing, NULL);
142
 
143
  strmaxcpy(Arg, pArg, sizeof(Arg));
144
  if ((pStart = strchr(Arg, '@')))
145
  {
146
    *pStart++ = '\0';
147
    if ((pLen = strchr(pStart, ',')))
148
    {
149
      *pLen++ = '\0';
150
      if ((pGran = strchr(pLen, ',')))
151
        *pGran++ = '\0';
152
    }
153
  }
154
 
155
  if (pStart && *pStart)
156
  {
157
    Start = ConstLongInt(pStart, &OK, 10);
158
    if (!OK)
159
      return ArgError(Num_ErrMsgInvalidNumericValue, pStart);
160
  }
161
  else
162
    Start = 0;
163
 
164
  if (pLen && *pLen)
165
  {
166
    Len = ConstLongInt(pLen, &OK, 10);
167
    if (!OK)
168
      return ArgError(Num_ErrMsgInvalidNumericValue, pLen);
169
  }
170
  else
171
    Len = 0;
172
 
173
  if (pGran && *pGran)
174
  {
175
    Gran = ConstLongInt(pGran, &OK, 10);
176
    if (!OK)
177
      return ArgError(Num_ErrMsgInvalidNumericValue, pGran);
178
  }
179
  else
180
    Gran = 1;
181
 
182
  InitCodeChunk(&Chunk);
183
  if (ReadCodeChunk(&Chunk, Arg, Start, Len, Gran))
184
    return ArgError(Num_ErrMsgCannotReadBinaryFile, Arg);
185
  MoveCodeChunkToList(&CodeChunks, &Chunk, TRUE);
186
 
187
  return e_cmd_arg;
188
}
189
 
190
static void ResizeBuffer(Byte* *ppBuffer, LargeWord *pAllocLen, LargeWord ReqLen)
191
{
192
  if (ReqLen > *pAllocLen)
193
  {
194
    Byte *pNew = *ppBuffer ? realloc(*ppBuffer, ReqLen) : malloc(ReqLen);
195
    if (pNew)
196
    {
197
      *ppBuffer = pNew;
198
      *pAllocLen = ReqLen;
199
    }
200
  }
201
}
202
 
203
static Boolean GetByte(char* *ppLine, Byte *pResult)
204
{
205
  if (!as_isxdigit(**ppLine))
206
    return False;
207
  *pResult = isdigit(**ppLine) ? (**ppLine - '0') : (as_toupper(**ppLine) - 'A' + 10);
208
  (*ppLine)++;
209
  if (!as_isxdigit(**ppLine))
210
    return False;
211
  *pResult = (*pResult << 4) | (isdigit(**ppLine) ? (**ppLine - '0') : (as_toupper(**ppLine) - 'A' + 10));
212
  (*ppLine)++;
213
  return True;
214
}
215
 
216
static void FlushChunk(tCodeChunk *pChunk)
217
{
218
  pChunk->Granularity = 1;
219
  pChunk->pLongCode = (LongWord*)pChunk->pCode;
220
  pChunk->pWordCode = (Word*)pChunk->pCode;
221
  MoveCodeChunkToList(&CodeChunks, pChunk, TRUE);
222
  InitCodeChunk(pChunk);
223
}
224
 
225
/* ------------------------------------------------------- */
226
 
227
static Boolean write_version_exit, write_help_exit, write_cpu_list_exit;
228
 
229
static int screen_height = 0;
230
 
231
static void write_console_next(const char *p_line)
232
{
233
  static int LineZ;
234
 
235
  WrConsoleLine(p_line, True);
236
  if (screen_height && (++LineZ >= screen_height))
237
  {
238
    LineZ = 0;
239
    WrConsoleLine(getmessage(Num_KeyWaitMsg), False);
240
    fflush(stdout);
241
    while (getchar() != '\n');
242
  }
243
}
244
 
245
static as_cmd_result_t CMD_HexFile(Boolean Negate, const char *pArg)
246
{
247
  FILE *pFile;
248
  char Line[300], *pLine;
249
  size_t Len;
250
  Byte *pLineBuffer = NULL, *pDataBuffer = 0, RecordType, Tmp;
251
  LargeWord LineBufferStart = 0, LineBufferAllocLen = 0, LineBufferLen = 0,
252
            Sum;
253
  tCodeChunk Chunk;
254
  unsigned z;
255
 
256
  if (Negate || !*pArg)
257
    return ArgError(Num_ErrMsgFileArgumentMissing, NULL);
258
 
259
  pFile = fopen(pArg, "r");
260
  if (!pFile)
261
  {
262
    return ArgError(Num_ErrMsgCannotReadHexFile, pArg);
263
  }
264
 
265
  InitCodeChunk(&Chunk);
266
  while (!feof(pFile))
267
  {
268
    fgets(Line, sizeof(Line), pFile);
269
    Len = strlen(Line);
270
    if ((Len > 0) && (Line[Len -1] == '\n'))
271
      Line[--Len] = '\0';
272
    if ((Len > 0) && (Line[Len -1] == '\r'))
273
      Line[--Len] = '\0';
274
    if (*Line != ':')
275
      continue;
276
 
277
    Sum = 0;
278
    pLine = Line + 1;
279
    if (!GetByte(&pLine, &Tmp))
280
      return ArgError(Num_ErrMsgInvalidHexData, pArg);
281
    ResizeBuffer(&pLineBuffer, &LineBufferAllocLen, Tmp);
282
    LineBufferLen = Tmp;
283
    Sum += Tmp;
284
 
285
    LineBufferStart = 0;
286
    for (z = 0; z < 2; z++)
287
    {
288
      if (!GetByte(&pLine, &Tmp))
289
        return ArgError(Num_ErrMsgInvalidHexData, pArg);
290
      LineBufferStart = (LineBufferStart << 8) | Tmp;
291
      Sum += Tmp;
292
    }
293
 
294
    if (!GetByte(&pLine, &RecordType))
295
      return ArgError(Num_ErrMsgInvalidHexData, pArg);
296
    Sum += RecordType;
297
    if (RecordType != 0)
298
      continue;
299
 
300
    for (z = 0; z < LineBufferLen; z++)
301
    {
302
      if (!GetByte(&pLine, &pLineBuffer[z]))
303
        return ArgError(Num_ErrMsgInvalidHexData, pArg);
304
      Sum += pLineBuffer[z];
305
    }
306
 
307
    if (!GetByte(&pLine, &Tmp))
308
      return ArgError(Num_ErrMsgInvalidHexData, pArg);
309
    Sum += Tmp;
310
    if (Sum & 0xff)
311
      return ArgError(Num_ErrMsgHexDataChecksumError, pArg);
312
 
313
    if (Chunk.Start + Chunk.Length == LineBufferStart)
314
    {
315
      ResizeBuffer(&Chunk.pCode, &Chunk.Length, Chunk.Length + LineBufferLen);
316
      memcpy(&Chunk.pCode[Chunk.Length - LineBufferLen], pLineBuffer, LineBufferLen);
317
    }
318
    else
319
    {
320
      if (Chunk.Length)
321
        FlushChunk(&Chunk);
322
      ResizeBuffer(&Chunk.pCode, &Chunk.Length, LineBufferLen);
323
      memcpy(Chunk.pCode, pLineBuffer, LineBufferLen);
324
      Chunk.Start = LineBufferStart;
325
    }
326
  }
327
  if (Chunk.Length)
328
    FlushChunk(&Chunk);
329
 
330
  if (pLineBuffer)
331
    free(pLineBuffer);
332
  if (pDataBuffer)
333
    free(pDataBuffer);
334
  fclose(pFile);
335
  return e_cmd_ok;
336
}
337
 
338
static as_cmd_result_t CMD_EntryAddress(Boolean Negate, const char *pArg)
339
{
340
  LargeWord Address;
341
  char *pName = NULL;
342
  String Arg, Str;
343
  Boolean OK;
344
 
345
  if (Negate || !*pArg)
346
    return ArgError(Num_ErrMsgAddressArgumentMissing, NULL);
347
 
348
  strmaxcpy(Arg, pArg, sizeof(Arg));
349
  if ((pName = ParenthPos(Arg, ',')))
350
    *pName++ = '\0';
351
 
352
  if (*Arg)
353
  {
354
    if (*Arg == '(')
355
    {
356
      Byte Vector[8];
357
      char *pVectorAddress = NULL, *pAddrLen = NULL, *pEndianess = NULL;
358
      LargeWord AddrLen, VectorAddress = 0, z;
359
      Boolean VectorMSB;
360
      int l;
361
 
362
      pVectorAddress = Arg + 1;
363
      l = strlen(pVectorAddress);
364
      if (pVectorAddress[l - 1] != ')')
365
        return ArgError(Num_ErrMsgClosingPatentheseMissing, pVectorAddress);
366
      pVectorAddress[l - 1] = '\0';
367
 
368
      if ((pAddrLen = strchr(pVectorAddress, ',')))
369
      {
370
        *pAddrLen++ = '\0';
371
        if ((pEndianess = strchr(pAddrLen, ',')))
372
          *pEndianess++ = '\0';
373
      }
374
 
375
      if (pVectorAddress && *pVectorAddress)
376
      {
377
        VectorAddress = ConstLongInt(pVectorAddress, &OK, 10);
378
        if (!OK)
379
          return ArgError(Num_ErrMsgInvalidNumericValue, pVectorAddress);
380
      }
381
      else
382
        pVectorAddress = 0;
383
 
384
      if (pAddrLen && *pAddrLen)
385
      {
386
        AddrLen = ConstLongInt(pAddrLen, &OK, 10);
387
        if (!OK || (AddrLen > sizeof(Vector)))
388
          return ArgError(Num_ErrMsgInvalidNumericValue, pAddrLen);
389
      }
390
      else
391
        AddrLen = 1;
392
 
393
      if (pEndianess && *pEndianess)
394
      {
395
        if (!as_strcasecmp(pEndianess, "MSB"))
396
          VectorMSB = True;
397
        else if (!as_strcasecmp(pEndianess, "LSB"))
398
          VectorMSB = False;
399
        else
400
          return ArgError(Num_ErrMsgInvalidEndinaness, pEndianess);
401
      }
402
      else
403
        VectorMSB = True; /* TODO: depend on CPU */
404
 
405
      if (!RetrieveCodeFromChunkList(&CodeChunks, VectorAddress, Vector, AddrLen))
406
        return ArgError(Num_ErrMsgCannotRetrieveEntryAddressData, NULL);
407
 
408
      Address = 0;
409
      for (z = 0; z < AddrLen; z++)
410
      {
411
        Address <<= 8;
412
        Address |= VectorMSB ? Vector[z] : Vector[AddrLen - 1 - z];
413
      }
414
      as_snprintf(Str, sizeof Str, "indirect address @ %lllx -> 0x%lllx", VectorAddress, Address);
415
      printf("%s\n", Str);
416
      AddChunk(&UsedDataChunks, VectorAddress, AddrLen, True);
417
 
418
      if (pName && *pName)
419
      {
420
        String Str;
421
 
422
        as_snprintf(Str, sizeof(Str), "Vector_2_%s", pName);
423
        AddInvSymbol(Str, VectorAddress);
424
      }
425
    }
426
    else
427
    {
428
      Address = ConstLongInt(pArg, &OK, 10);
429
      if (!OK)
430
        return ArgError(Num_ErrMsgInvalidNumericValue, pArg);
431
    }
432
  }
433
  else
434
    Address = 0;
435
 
436
  if (pName && *pName)
437
    AddInvSymbol(pName, Address);
438
  AddEntryAddress(Address);
439
 
440
  return e_cmd_arg;
441
}
442
 
443
static as_cmd_result_t CMD_Symbol(Boolean Negate, const char *pArg)
444
{
445
  LargeWord Address;
446
  char *pName = NULL;
447
  String Arg;
448
  Boolean OK;
449
 
450
  if (Negate || !*pArg)
451
    return ArgError(Num_ErrMsgSymbolArgumentMissing, NULL);
452
 
453
  strmaxcpy(Arg, pArg, sizeof(Arg));
454
  if ((pName = strchr(Arg, '=')))
455
    *pName++ = '\0';
456
 
457
  if (*Arg)
458
  {
459
    Address = ConstLongInt(Arg, &OK, 10);
460
    if (!OK)
461
      return ArgError(Num_ErrMsgInvalidNumericValue, Arg);
462
  }
463
  else
464
    Address = 0;
465
 
466
  if (pName && *pName)
467
    AddInvSymbol(pName, Address);
468
 
469
  return e_cmd_arg;
470
}
471
 
472
static as_cmd_result_t CMD_CPU(Boolean Negate, const char *pArg)
473
{
474
  const tCPUDef *pCPUDef;
475
 
476
  if (Negate || !*pArg)
477
    return ArgError(Num_ErrMsgCPUArgumentMissing, NULL);
478
 
479
  if (!as_strcasecmp(pArg, "?") || !as_strcasecmp(pArg, "LIST"))
480
  {
481
    write_cpu_list_exit = True;
482
    return e_cmd_ok;
483
  }
484
 
485
  pCPUDef = LookupCPUDefByName(pArg);
486
  if (!pCPUDef)
487
    return ArgError(Num_ErrMsgUnknownCPU, pArg);
488
 
489
  pCPUDef->SwitchProc(pCPUDef->pUserData);
490
 
491
  return e_cmd_arg;
492
}
493
 
494
static as_cmd_result_t CMD_HexLowerCase(Boolean Negate, const char *Arg)
495
{
496
  UNUSED(Arg);
497
 
498
  HexStartCharacter = Negate ? 'A' : 'a';
499
  return e_cmd_ok;
500
}
501
 
502
static as_cmd_result_t CMD_PrintVersion(Boolean Negate, const char *Arg)
503
{
504
  UNUSED(Arg);
505
 
506
  if (Negate)
507
    return e_cmd_err;
508
 
509
  write_version_exit = True;
510
  return e_cmd_ok;
511
}
512
 
513
static as_cmd_result_t CMD_PrintHelp(Boolean Negate, const char *Arg)
514
{
515
  UNUSED(Arg);
516
 
517
  if (Negate)
518
    return e_cmd_err;
519
 
520
  write_help_exit = True;
521
  return e_cmd_ok;
522
}
523
 
524
static as_cmd_result_t CMD_screen_height(Boolean negate, const char *p_arg)
525
{
526
  Boolean ok;
527
  int new_screen_height;
528
 
529
  if (negate)
530
  {
531
    screen_height = 0;
532
    return e_cmd_ok;
533
  }
534
  new_screen_height = ConstLongInt(p_arg, &ok, 10);
535
  if (!ok)
536
    return e_cmd_err;
537
  screen_height = new_screen_height;
538
  return e_cmd_arg;
539
}
540
 
541
static as_cmd_rec_t DASParams[] =
542
{
543
  { "CPU"             , CMD_CPU             },
544
  { "BINFILE"         , CMD_BinFile         },
545
  { "HEXFILE"         , CMD_HexFile         },
546
  { "ENTRYADDRESS"    , CMD_EntryAddress    },
547
  { "SCREENHEIGHT"    , CMD_screen_height   },
548
  { "SYMBOL"          , CMD_Symbol          },
549
  { "h"               , CMD_HexLowerCase    },
550
  { "HELP"            , CMD_PrintHelp       },
551
  { "VERSION"         , CMD_PrintVersion    }
552
};
553
 
554
typedef struct
555
{
556
  FILE *pDestFile;
557
  int MaxSrcLineLen, MaxLabelLen;
558
} tDisasmData;
559
 
560
static void DisasmIterator(const OneChunk *pChunk, Boolean IsData, void *pUser)
561
{
562
  LargeWord Address;
563
  char NumString[50];
564
  tDisassInfo Info;
565
  tDisasmData *pData = (tDisasmData*)pUser;
566
  const char *pLabel;
567
  Byte Code[100];
568
  unsigned z;
569
  int DataSize = -1;
570
 
571
  Address = pChunk->Start;
572
  HexString(NumString, sizeof(NumString), Address, 0);
573
  fprintf(pData->pDestFile, "\n");
574
  PrTabs(pData->pDestFile, pData->MaxLabelLen, 0);
575
  fprintf(pData->pDestFile, "org\t$%s\n", NumString);
576
  while (Address < pChunk->Start + pChunk->Length)
577
  {
578
    pLabel = LookupInvSymbol(Address);
579
    if (pLabel && !strncmp(pLabel, "Vector_", 7) && IsData)
580
    {
581
      String Num;
582
      char *pEnd = strchr(pLabel + 7, '_');
583
 
584
      if (pEnd)
585
      {
586
        int l = pEnd - (pLabel + 7);
587
 
588
        memcpy(Num, pLabel + 7, l);
589
        Num[l] = '\0';
590
        DataSize = strtol(Num, &pEnd, 10);
591
        if (*pEnd)
592
          DataSize = -1;
593
      }
594
    }
595
 
596
    Disassemble(Address, &Info, IsData, DataSize);
597
    if (Info.pRemark)
598
    {
599
      PrTabs(pData->pDestFile, pData->MaxLabelLen, 0);
600
      fprintf(pData->pDestFile, "; %s\n", Info.pRemark);
601
    }
602
 
603
    if (pLabel)
604
    {
605
      fprintf(pData->pDestFile, "%s:", pLabel);
606
      PrTabs(pData->pDestFile, pData->MaxLabelLen, tabbedstrlen(pLabel) + 1);
607
    }
608
    else
609
      PrTabs(pData->pDestFile, pData->MaxLabelLen, 0);
610
    fprintf(pData->pDestFile, "%s", Info.SrcLine);
611
 
612
    PrTabs(pData->pDestFile, pData->MaxSrcLineLen, tabbedstrlen(Info.SrcLine));
613
    fprintf(pData->pDestFile, ";");
614
    RetrieveCodeFromChunkList(&CodeChunks, Address, Code, Info.CodeLen);
615
    for (z = 0; z < Info.CodeLen; z++)
616
    {
617
      HexString(NumString, sizeof(NumString),  Code[z], 2);
618
      fprintf(pData->pDestFile, " %s", NumString);
619
    }
620
    fputc('\n', pData->pDestFile);
621
 
622
    Address += Info.CodeLen;
623
  }
624
}
625
 
626
int main(int argc, char **argv)
627
{
628
  LargeWord Address, NextAddress;
629
  Boolean NextAddressValid;
630
  tDisassInfo Info;
631
  unsigned z;
632
  tDisasmData Data;
633
  int ThisSrcLineLen;
634
  as_cmd_results_t cmd_results;
635
 
636
  strutil_init();
637
  nls_init();
638
  NLS_Initialize(&argc, argv);
639
  dasmdef_init();
640
  cpulist_init();
641
  msg_level_init();
642
  nlmessages_init("das.msg", *argv, MsgId1, MsgId2);
643
  deco68_init();
644
  deco87c800_init();
645
  deco4004_init();
646
  write_version_exit = write_help_exit = write_cpu_list_exit = False;
647
 
648
  as_cmd_register(DASParams, as_array_size(DASParams));
649
  if (e_cmd_err == as_cmd_process(argc, argv, pEnvName, &cmd_results))
650
  {
651
    fprintf(stderr, "%s%s\n", getmessage(cmd_results.error_arg_in_env ? Num_ErrMsgInvEnvParam : Num_ErrMsgInvParam), cmd_results.error_arg);
652
    exit(4);
653
  }
654
 
655
  if ((msg_level >= e_msg_level_verbose) || write_version_exit)
656
  {
657
    String Ver;
658
 
659
    as_snprintf(Ver, sizeof(Ver), "DAS V%s", Version);
660
    WrCopyRight(Ver);
661
  }
662
 
663
  if (write_help_exit)
664
  {
665
    char *ph1, *ph2;
666
    String Tmp;
667
    as_snprintf(Tmp, sizeof(Tmp), "%s%s%s", getmessage(Num_InfoMessHead1), as_cmdarg_get_executable_name(), getmessage(Num_InfoMessHead2));
668
    write_console_next(Tmp);
669
    for (ph1 = getmessage(Num_InfoMessHelp), ph2 = strchr(ph1, '\n'); ph2; ph1 = ph2 + 1, ph2 = strchr(ph1, '\n'))
670
    {
671
      *ph2 = '\0';
672
      write_console_next(ph1);
673
      *ph2 = '\n';
674
    }
675
  }
676
 
677
  if (write_cpu_list_exit)
678
  {
679
    printf("%s\n", getmessage(Num_InfoMessCPUList));
680
    PrintCPUList(write_console_next);
681
  }
682
 
683
  if (write_version_exit || write_help_exit || write_cpu_list_exit)
684
    exit(0);
685
 
686
  if (!Disassemble)
687
  {
688
    fprintf(stderr, "no CPU set, aborting\n");
689
    exit(3);
690
  }
691
 
692
  /* walk through code */
693
 
694
  NextAddress = 0;
695
  NextAddressValid = False;
696
  Data.MaxSrcLineLen = 0;
697
  while (EntryAddressAvail())
698
  {
699
    Address = GetEntryAddress(NextAddressValid, NextAddress);
700
    Disassemble(Address, &Info, False, -1);
701
    AddChunk(&UsedCodeChunks, Address, Info.CodeLen, True);
702
    if ((ThisSrcLineLen = tabbedstrlen(Info.SrcLine)) > Data.MaxSrcLineLen)
703
      Data.MaxSrcLineLen = ThisSrcLineLen;
704
    for (z = 0; z < Info.NextAddressCount; z++)
705
      if (!AddressInChunk(&UsedCodeChunks, Info.NextAddresses[z]))
706
        AddEntryAddress(Info.NextAddresses[z]);
707
    NextAddress = Address + Info.CodeLen;
708
    NextAddressValid = True;
709
  }
710
 
711
  /* round up src line & symbol length to next multiple of tabs */
712
 
713
  Data.MaxSrcLineLen += TABSIZE - (Data.MaxSrcLineLen % TABSIZE);
714
  Data.MaxLabelLen = GetMaxInvSymbolNameLen() + 1;
715
  Data.MaxLabelLen += TABSIZE - (Data.MaxLabelLen % TABSIZE);
716
  Data.pDestFile = stdout;
717
 
718
  /* bring areas into order */
719
 
720
  SortChunks(&UsedCodeChunks);
721
  SortChunks(&UsedDataChunks);
722
 
723
  /* dump them out */
724
 
725
  IterateChunks(DisasmIterator, &Data);
726
 
727
  /* summary */
728
 
729
  DumpChunks(&UsedCodeChunks, Data.pDestFile);
730
 
731
  return 0;
732
}