Advertisement
Guest User

Untitled

a guest
Nov 24th, 2013
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 31.42 KB | None | 0 0
  1. /*                                                                           */
  2. /*                                  main.c                                   */
  3. /*                                                                           */
  4. /*                 Main program for the ca65 macroassembler                  */
  5. /*                                                                           */
  6. /*                                                                           */
  7. /*                                                                           */
  8. /* (C) 1998-2013, Ullrich von Bassewitz                                      */
  9. /*                Roemerstrasse 52                                           */
  10. /*                D-70794 Filderstadt                                        */
  11. /* EMail:         uz@cc65.org                                                */
  12. /*                                                                           */
  13. /*                                                                           */
  14. /* This software is provided 'as-is', without any expressed or implied       */
  15. /* warranty.  In no event will the authors be held liable for any damages    */
  16. /* arising from the use of this software.                                    */
  17. /*                                                                           */
  18. /* Permission is granted to anyone to use this software for any purpose,     */
  19. /* including commercial applications, and to alter it and redistribute it    */
  20. /* freely, subject to the following restrictions:                            */
  21. /*                                                                           */
  22. /* 1. The origin of this software must not be misrepresented; you must not   */
  23. /*    claim that you wrote the original software. If you use this software   */
  24. /*    in a product, an acknowledgment in the product documentation would be  */
  25. /*    appreciated but is not required.                                       */
  26. /* 2. Altered source versions must be plainly marked as such, and must not   */
  27. /*    be misrepresented as being the original software.                      */
  28. /* 3. This notice may not be removed or altered from any source              */
  29. /*    distribution.                                                          */
  30. /*                                                                           */
  31. /*****************************************************************************/
  32.  
  33.  
  34.  
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <time.h>
  39.  
  40. /* common */
  41. #include "addrsize.h"
  42. #include "chartype.h"
  43. #include "cmdline.h"
  44. #include "debugflag.h"
  45. #include "mmodel.h"
  46. #include "print.h"
  47. #include "scopedefs.h"
  48. #include "strbuf.h"
  49. #include "target.h"
  50. #include "tgttrans.h"
  51. #include "version.h"
  52.  
  53. /* ca65 */
  54. #include "abend.h"
  55. #include "asserts.h"
  56. #include "dbginfo.h"
  57. #include "error.h"
  58. #include "expr.h"
  59. #include "feature.h"
  60. #include "filetab.h"
  61. #include "global.h"
  62. #include "incpath.h"
  63. #include "instr.h"
  64. #include "istack.h"
  65. #include "lineinfo.h"
  66. #include "listing.h"
  67. #include "macro.h"
  68. #include "nexttok.h"
  69. #include "objfile.h"
  70. #include "options.h"
  71. #include "pseudo.h"
  72. #include "scanner.h"
  73. #include "segment.h"
  74. #include "sizeof.h"
  75. #include "span.h"
  76. #include "spool.h"
  77. #include "symbol.h"
  78. #include "symtab.h"
  79. #include "ulabel.h"
  80.  
  81.  
  82.  
  83. /*****************************************************************************/
  84. /*                                   Code                                    */
  85. /*****************************************************************************/
  86.  
  87.  
  88.  
  89. static void Usage (void)
  90. /* Print usage information and exit */
  91. {
  92.     printf ("Usage: %s [options] file\n"
  93.             "Short options:\n"
  94.             "  -D name[=value]\t\tDefine a symbol\n"
  95.             "  -I dir\t\t\tSet an include directory search path\n"
  96.             "  -U\t\t\t\tMark unresolved symbols as import\n"
  97.             "  -V\t\t\t\tPrint the assembler version\n"
  98.             "  -W n\t\t\t\tSet warning level n\n"
  99.             "  -d\t\t\t\tDebug mode\n"
  100.             "  -g\t\t\t\tAdd debug info to object file\n"
  101.             "  -h\t\t\t\tHelp (this text)\n"
  102.             "  -i\t\t\t\tIgnore case of symbols\n"
  103.             "  -l name\t\t\tCreate a listing file if assembly was ok\n"
  104.             "  -mm model\t\t\tSet the memory model\n"
  105.             "  -o name\t\t\tName the output file\n"
  106.             "  -s\t\t\t\tEnable smart mode\n"
  107.             "  -t sys\t\t\tSet the target system\n"
  108.             "  -v\t\t\t\tIncrease verbosity\n"
  109.             "\n"
  110.             "Long options:\n"
  111.             "  --auto-import\t\t\tMark unresolved symbols as import\n"
  112.             "  --bin-include-dir dir\t\tSet a search path for binary includes\n"
  113.             "  --cpu type\t\t\tSet cpu type\n"
  114.             "  --create-dep name\t\tCreate a make dependency file\n"
  115.             "  --create-full-dep name\tCreate a full make dependency file\n"
  116.             "  --debug\t\t\tDebug mode\n"
  117.             "  --debug-info\t\t\tAdd debug info to object file\n"
  118.             "  --feature name\t\tSet an emulation feature\n"
  119.             "  --help\t\t\tHelp (this text)\n"
  120.             "  --ignore-case\t\t\tIgnore case of symbols\n"
  121.             "  --include-dir dir\t\tSet an include directory search path\n"
  122.             "  --large-alignment\t\tDon't warn about large alignments\n"
  123.             "  --listing name\t\tCreate a listing file if assembly was ok\n"
  124.             "  --list-bytes n\t\tMaximum number of bytes per listing line\n"
  125.             "  --macpack-dir dir\t\tSet a macro package directory\n"
  126.             "  --memory-model model\t\tSet the memory model\n"
  127.             "  --pagelength n\t\tSet the page length for the listing\n"
  128.             "  --relax-checks\t\tRelax some checks (see docs)\n"
  129.             "  --smart\t\t\tEnable smart mode\n"
  130.             "  --target sys\t\t\tSet the target system\n"
  131.             "  --verbose\t\t\tIncrease verbosity\n"
  132.             "  --version\t\t\tPrint the assembler version\n",
  133.             ProgName);
  134. }
  135.  
  136.  
  137.  
  138. static void SetOptions (void)
  139. /* Set the option for the translator */
  140. {
  141.     StrBuf Buf = STATIC_STRBUF_INITIALIZER;
  142.  
  143.     /* Set the translator */
  144.     SB_Printf (&Buf, "ca65 V%s", GetVersionAsString ());
  145.     OptTranslator (&Buf);
  146.  
  147.     /* Set date and time */
  148.     OptDateTime ((unsigned long) time(0));
  149.  
  150.     /* Release memory for the string */
  151.     SB_Done (&Buf);
  152. }
  153.  
  154.  
  155.  
  156. static void NewSymbol (const char* SymName, long Val)
  157. /* Define a symbol with a fixed numeric value in the current scope */
  158. {
  159.     ExprNode* Expr;
  160.     SymEntry* Sym;
  161.  
  162.     /* Convert the name to a string buffer */
  163.     StrBuf SymBuf = STATIC_STRBUF_INITIALIZER;
  164.     SB_CopyStr (&SymBuf, SymName);
  165.  
  166.     /* Search for the symbol, allocate a new one if it doesn't exist */
  167.     Sym = SymFind (CurrentScope, &SymBuf, SYM_ALLOC_NEW);
  168.  
  169.     /* Check if have already a symbol with this name */
  170.     if (SymIsDef (Sym)) {
  171.         AbEnd ("`%s' is already defined", SymName);
  172.     }
  173.  
  174.     /* Generate an expression for the symbol */
  175.     Expr = GenLiteralExpr (Val);
  176.  
  177.     /* Mark the symbol as defined */
  178.     SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_NONE);
  179.  
  180.     /* Free string buffer memory */
  181.     SB_Done (&SymBuf);
  182. }
  183.  
  184.  
  185.  
  186. static void CBMSystem (const char* Sys)
  187. /* Define a CBM system */
  188. {
  189.     NewSymbol ("__CBM__", 1);
  190.     NewSymbol (Sys, 1);
  191. }
  192.  
  193.  
  194.  
  195. static void SetSys (const char* Sys)
  196. /* Define a target system */
  197. {
  198.     switch (Target = FindTarget (Sys)) {
  199.  
  200.         case TGT_NONE:
  201.             break;
  202.  
  203.         case TGT_MODULE:
  204.             AbEnd ("Cannot use `module' as a target for the assembler");
  205.             break;
  206.  
  207.         case TGT_ATARI:
  208.             NewSymbol ("__ATARI__", 1);
  209.             break;
  210.  
  211.         case TGT_ATARIXL:
  212.             NewSymbol ("__ATARI__", 1);
  213.             NewSymbol ("__ATARIXL__", 1);
  214.             break;
  215.  
  216.         case TGT_C16:
  217.             CBMSystem ("__C16__");
  218.             break;
  219.  
  220.         case TGT_C64:
  221.             CBMSystem ("__C64__");
  222.             break;
  223.  
  224.         case TGT_VIC20:
  225.             CBMSystem ("__VIC20__");
  226.             break;
  227.  
  228.         case TGT_C128:
  229.             CBMSystem ("__C128__");
  230.             break;
  231.  
  232.         case TGT_PLUS4:
  233.             CBMSystem ("__C16__");
  234.             NewSymbol ("__PLUS4__", 1);
  235.             break;
  236.  
  237.         case TGT_CBM510:
  238.             CBMSystem ("__CBM510__");
  239.             break;
  240.  
  241.         case TGT_CBM610:
  242.             CBMSystem ("__CBM610__");
  243.             break;
  244.  
  245.         case TGT_PET:
  246.             CBMSystem ("__PET__");
  247.             break;
  248.  
  249.         case TGT_BBC:
  250.             NewSymbol ("__BBC__", 1);
  251.             break;
  252.  
  253.         case TGT_APPLE2:
  254.             NewSymbol ("__APPLE2__", 1);
  255.             break;
  256.  
  257.         case TGT_APPLE2ENH:
  258.             NewSymbol ("__APPLE2__", 1);
  259.             NewSymbol ("__APPLE2ENH__", 1);
  260.             break;
  261.  
  262.         case TGT_GEOS_CBM:
  263.             /* Do not handle as a CBM system */
  264.             NewSymbol ("__GEOS__", 1);
  265.             NewSymbol ("__GEOS_CBM__", 1);
  266.             break;
  267.  
  268.         case TGT_GEOS_APPLE:
  269.             NewSymbol ("__GEOS__", 1);
  270.             NewSymbol ("__GEOS_APPLE__", 1);
  271.             break;
  272.  
  273.         case TGT_LUNIX:
  274.             NewSymbol ("__LUNIX__", 1);
  275.             break;
  276.  
  277.         case TGT_ATMOS:
  278.             NewSymbol ("__ATMOS__", 1);
  279.             break;
  280.  
  281.         case TGT_NES:
  282.             NewSymbol ("__NES__", 1);
  283.             break;
  284.  
  285.         case TGT_SUPERVISION:
  286.             NewSymbol ("__SUPERVISION__", 1);
  287.             break;
  288.  
  289.         case TGT_LYNX:
  290.             NewSymbol ("__LYNX__", 1);
  291.             break;
  292.  
  293.         case TGT_SIM6502:
  294.             NewSymbol ("__SIM6502__", 1);
  295.             break;
  296.  
  297.         case TGT_SIM65C02:
  298.             NewSymbol ("__SIM65C02__", 1);
  299.             break;
  300.  
  301.         default:
  302.             AbEnd ("Invalid target name: `%s'", Sys);
  303.  
  304.     }
  305.  
  306.     /* Initialize the translation tables for the target system */
  307.     TgtTranslateInit ();
  308. }
  309.  
  310.  
  311.  
  312. static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name)
  313. /* Handle an option that remembers a file name for later */
  314. {
  315.     /* Cannot have the option twice */
  316.     if (SB_NotEmpty (Name)) {
  317.         AbEnd ("Cannot use option `%s' twice", Opt);
  318.     }
  319.     /* Remember the file name for later */
  320.     SB_CopyStr (Name, Arg);
  321.     SB_Terminate (Name);
  322. }
  323.  
  324.  
  325.  
  326. static void DefineSymbol (const char* Def)
  327. /* Define a symbol from the command line */
  328. {
  329.     const char* P;
  330.     long Val;
  331.     StrBuf SymName = AUTO_STRBUF_INITIALIZER;
  332.  
  333.  
  334.     /* The symbol must start with a character or underline */
  335.     if (!IsIdStart (Def [0])) {
  336.         InvDef (Def);
  337.     }
  338.     P = Def;
  339.  
  340.     /* Copy the symbol, checking the rest */
  341.     while (IsIdChar (*P)) {
  342.         SB_AppendChar (&SymName, *P++);
  343.     }
  344.     SB_Terminate (&SymName);
  345.  
  346.     /* Do we have a value given? */
  347.     if (*P != '=') {
  348.         if (*P != '\0') {
  349.             InvDef (Def);
  350.         }
  351.         Val = 0;
  352.     } else {
  353.         /* We have a value */
  354.         ++P;
  355.         if (*P == '$') {
  356.             ++P;
  357.             if (sscanf (P, "%lx", &Val) != 1) {
  358.                 InvDef (Def);
  359.             }
  360.         } else {
  361.             if (sscanf (P, "%li", &Val) != 1) {
  362.                 InvDef (Def);
  363.             }
  364.         }
  365.     }
  366.  
  367.     /* Define the new symbol */
  368.     NewSymbol (SB_GetConstBuf (&SymName), Val);
  369.  
  370.     /* Release string memory */
  371.     SB_Done (&SymName);
  372. }
  373.  
  374.  
  375.  
  376. static void OptAutoImport (const char* Opt attribute ((unused)),
  377.                            const char* Arg attribute ((unused)))
  378. /* Mark unresolved symbols as imported */
  379. {
  380.     AutoImport = 1;
  381. }
  382.  
  383.  
  384.  
  385. static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char* Arg)
  386. /* Add an include search path for binaries */
  387. {
  388.     AddSearchPath (BinSearchPath, Arg);
  389. }
  390.  
  391.  
  392.  
  393. static void OptCPU (const char* Opt attribute ((unused)), const char* Arg)
  394. /* Handle the --cpu option */
  395. {
  396.     cpu_t CPU = FindCPU (Arg);
  397.     if (CPU == CPU_UNKNOWN) {
  398.         AbEnd ("Invalid CPU: `%s'", Arg);
  399.     } else {
  400.         SetCPU (CPU);
  401.     }
  402. }
  403.  
  404.  
  405.  
  406. static void OptCreateDep (const char* Opt, const char* Arg)
  407. /* Handle the --create-dep option */
  408. {
  409.     FileNameOption (Opt, Arg, &DepName);
  410. }
  411.  
  412.  
  413.  
  414. static void OptCreateFullDep (const char* Opt attribute ((unused)),
  415.                               const char* Arg)
  416. /* Handle the --create-full-dep option */
  417. {
  418.     FileNameOption (Opt, Arg, &FullDepName);
  419. }
  420.  
  421.  
  422.  
  423. static void OptDebug (const char* Opt attribute ((unused)),
  424.                       const char* Arg attribute ((unused)))
  425. /* Compiler debug mode */
  426. {
  427.     ++Debug;
  428. }
  429.  
  430.  
  431.  
  432. static void OptDebugInfo (const char* Opt attribute ((unused)),
  433.                           const char* Arg attribute ((unused)))
  434. /* Add debug info to the object file */
  435. {
  436.     DbgSyms = 1;
  437. }
  438.  
  439.  
  440.  
  441. static void OptFeature (const char* Opt attribute ((unused)), const char* Arg)
  442. /* Set an emulation feature */
  443. {
  444.     /* Make a string buffer from Arg */
  445.     StrBuf Feature;
  446.  
  447.     /* Set the feature, check for errors */
  448.     if (SetFeature (SB_InitFromString (&Feature, Arg)) == FEAT_UNKNOWN) {
  449.         AbEnd ("Illegal emulation feature: `%s'", Arg);
  450.     }
  451. }
  452.  
  453.  
  454.  
  455. static void OptHelp (const char* Opt attribute ((unused)),
  456.                      const char* Arg attribute ((unused)))
  457. /* Print usage information and exit */
  458. {
  459.     Usage ();
  460.     exit (EXIT_SUCCESS);
  461. }
  462.  
  463.  
  464.  
  465. static void OptIgnoreCase (const char* Opt attribute ((unused)),
  466.                            const char* Arg attribute ((unused)))
  467. /* Ignore case on symbols */
  468. {
  469.     IgnoreCase = 1;
  470. }
  471.  
  472.  
  473.  
  474. static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg)
  475. /* Add an include search path */
  476. {
  477.     AddSearchPath (IncSearchPath, Arg);
  478. }
  479.  
  480.  
  481.  
  482. static void OptLargeAlignment (const char* Opt attribute ((unused)),
  483.                                const char* Arg attribute ((unused)))
  484. /* Don't warn about large alignments */
  485. {
  486.     LargeAlignment = 1;
  487. }
  488.  
  489.  
  490.  
  491. static void OptListBytes (const char* Opt, const char* Arg)
  492. /* Set the maximum number of bytes per listing line */
  493. {
  494.     unsigned Num;
  495.     char     Check;
  496.  
  497.     /* Convert the argument to a number */
  498.     if (sscanf (Arg, "%u%c", &Num, &Check) != 1) {
  499.         InvArg (Opt, Arg);
  500.     }
  501.  
  502.     /* Check the bounds */
  503.     if (Num != 0 && (Num < MIN_LIST_BYTES || Num > MAX_LIST_BYTES)) {
  504.         AbEnd ("Argument for option `%s' is out of range", Opt);
  505.     }
  506.  
  507.     /* Use the value */
  508.     SetListBytes (Num);
  509. }
  510.  
  511.  
  512.  
  513. static void OptListing (const char* Opt, const char* Arg)
  514. /* Create a listing file */
  515. {
  516.     /* Since the meaning of -l and --listing has changed, print an error if
  517.      * the filename is empty or begins with the option char.
  518.      */
  519.     if (Arg == 0 || *Arg == '\0' || *Arg == '-') {
  520.         Fatal ("The meaning of `%s' has changed. It does now "
  521.                "expect a file name as argument.", Opt);
  522.     }
  523.  
  524.     /* Get the file name */
  525.     FileNameOption (Opt, Arg, &ListingName);
  526. }
  527.  
  528.  
  529.  
  530. static void OptMemoryModel (const char* Opt, const char* Arg)
  531. /* Set the memory model */
  532. {
  533.     mmodel_t M;
  534.  
  535.     /* Check the current memory model */
  536.     if (MemoryModel != MMODEL_UNKNOWN) {
  537.         AbEnd ("Cannot use option `%s' twice", Opt);
  538.     }
  539.  
  540.     /* Translate the memory model name and check it */
  541.     M = FindMemoryModel (Arg);
  542.     if (M == MMODEL_UNKNOWN) {
  543.         AbEnd ("Unknown memory model: %s", Arg);
  544.     } else if (M == MMODEL_HUGE) {
  545.         AbEnd ("Unsupported memory model: %s", Arg);
  546.     }
  547.  
  548.     /* Set the memory model */
  549.     SetMemoryModel (M);
  550. }
  551.  
  552.  
  553.  
  554. static void OptPageLength (const char* Opt attribute ((unused)), const char* Arg)
  555. /* Handle the --pagelength option */
  556. {
  557.     int Len = atoi (Arg);
  558.     if (Len != -1 && (Len < MIN_PAGE_LEN || Len > MAX_PAGE_LEN)) {
  559.         AbEnd ("Invalid page length: %d", Len);
  560.     }
  561.     PageLength = Len;
  562. }
  563.  
  564.  
  565.  
  566. static void OptRelaxChecks (const char* Opt attribute ((unused)),
  567.                             const char* Arg attribute ((unused)))
  568. /* Handle the --relax-checks options */
  569. {
  570.     RelaxChecks = 1;
  571. }
  572.  
  573.  
  574.  
  575. static void OptSmart (const char* Opt attribute ((unused)),
  576.                       const char* Arg attribute ((unused)))
  577. /* Handle the -s/--smart options */
  578. {
  579.     SmartMode = 1;
  580. }
  581.  
  582.  
  583.  
  584. static void OptTarget (const char* Opt attribute ((unused)), const char* Arg)
  585. /* Set the target system */
  586. {
  587.     SetSys (Arg);
  588. }
  589.  
  590.  
  591.  
  592. static void OptVerbose (const char* Opt attribute ((unused)),
  593.                         const char* Arg attribute ((unused)))
  594. /* Increase verbosity */
  595. {
  596.     ++Verbosity;
  597. }
  598.  
  599.  
  600.  
  601. static void OptVersion (const char* Opt attribute ((unused)),
  602.                         const char* Arg attribute ((unused)))
  603. /* Print the assembler version */
  604. {
  605.     fprintf (stderr, "ca65 V%s\n", GetVersionAsString ());
  606. }
  607.  
  608.  
  609.  
  610. static void DoPCAssign (void)
  611. /* Start absolute code */
  612. {
  613.     long PC = ConstExpression ();
  614.     if (PC < 0 || PC > 0xFFFFFF) {
  615.         Error ("Range error");
  616.     } else {
  617.         EnterAbsoluteMode (PC);
  618.     }
  619. }
  620.  
  621.  
  622.  
  623. static void OneLine (void)
  624. /* Assemble one line */
  625. {
  626.     Segment*      Seg   = 0;
  627.     unsigned long PC    = 0;
  628.     SymEntry*     Sym   = 0;
  629.     Macro*        Mac   = 0;
  630.     int           Instr = -1;
  631.  
  632.     /* Initialize the new listing line if we are actually reading from file
  633.      * and not from internally pushed input.
  634.      */
  635.     if (!HavePushedInput ()) {
  636.         InitListingLine ();
  637.     }
  638.  
  639.     /* Single colon means unnamed label */
  640.     if (CurTok.Tok == TOK_COLON) {
  641.         ULabDef ();
  642.         NextTok ();
  643.     }
  644.  
  645.     /* If the first token on the line is an identifier, check for a macro or
  646.      * an instruction.
  647.      */
  648.     if (CurTok.Tok == TOK_IDENT) {
  649.         if (UbiquitousIdents) {
  650.             /* Macros CAN be instructions, so check for them first */
  651.             Mac = FindMacro (&CurTok.SVal);
  652.             if (Mac == 0) {
  653.                 Instr = FindInstruction (&CurTok.SVal);
  654.             }
  655.            
  656.         } else {
  657.             /* Macros and symbols may NOT use the names of instructions */
  658.             Instr = FindInstruction (&CurTok.SVal);
  659.             if (Instr < 0) {
  660.                 Mac = FindMacro (&CurTok.SVal);
  661.             }
  662.         }
  663.     }
  664.  
  665.     /* Handle an identifier. This may be a cheap local symbol, or a fully
  666.      * scoped identifier which may start with a namespace token (for global
  667.      * namespace)
  668.      */
  669.     if (CurTok.Tok == TOK_LOCAL_IDENT ||
  670.         CurTok.Tok == TOK_NAMESPACE   ||
  671.         (CurTok.Tok == TOK_IDENT && Instr < 0 && Mac == 0)) {
  672.  
  673.         /* Did we have whitespace before the ident? */
  674.         int HadWS = CurTok.WS;
  675.  
  676.         /* Generate the symbol table entry, then skip the name */
  677.         Sym = ParseAnySymName (SYM_ALLOC_NEW);
  678.  
  679.         /* If a colon follows, this is a label definition. If there
  680.          * is no colon, it's an assignment.
  681.          */
  682.         if (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_ASSIGN) {
  683.  
  684.             /* Determine the symbol flags from the assignment token */
  685.             unsigned Flags = (CurTok.Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE;
  686.  
  687.             /* Skip the '=' */
  688.             NextTok ();
  689.  
  690.             /* Define the symbol with the expression following the '=' */
  691.             SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
  692.  
  693.             /* Don't allow anything after a symbol definition */
  694.             ConsumeSep ();
  695.             return;
  696.  
  697.         } else if (CurTok.Tok == TOK_SET) {
  698.  
  699.             ExprNode* Expr;
  700.  
  701.             /* .SET defines variables (= redefinable symbols) */
  702.             NextTok ();
  703.  
  704.             /* Read the assignment expression, which must be constant */
  705.             Expr = GenLiteralExpr (ConstExpression ());
  706.  
  707.             /* Define the symbol with the constant expression following
  708.              * the '='
  709.              */
  710.             SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR);
  711.  
  712.             /* Don't allow anything after a symbol definition */
  713.             ConsumeSep ();
  714.             return;
  715.  
  716.         } else {
  717.  
  718.             /* A label. Remember the current segment, so we can later
  719.              * determine the size of the data stored under the label.
  720.              */
  721.             Seg = ActiveSeg;
  722.             PC  = GetPC ();
  723.  
  724.             /* Define the label */
  725.             SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
  726.  
  727.             /* Skip the colon. If NoColonLabels is enabled, allow labels
  728.              * without a colon if there is no whitespace before the
  729.              * identifier.
  730.              */
  731.             if (CurTok.Tok != TOK_COLON) {
  732.                 if (HadWS || !NoColonLabels) {
  733.                     Error ("`:' expected");
  734.                     /* Try some smart error recovery */
  735.                     if (CurTok.Tok == TOK_NAMESPACE) {
  736.                         NextTok ();
  737.                     }
  738.                 }
  739.             } else {
  740.                 /* Skip the colon */
  741.                 NextTok ();
  742.             }
  743.  
  744.             /* If we come here, a new identifier may be waiting, which may
  745.              * be a macro or instruction.
  746.              */
  747.             if (CurTok.Tok == TOK_IDENT) {
  748.                 if (UbiquitousIdents) {
  749.                     /* Macros CAN be instructions, so check for them first */
  750.                     Mac = FindMacro (&CurTok.SVal);
  751.                     if (Mac == 0) {
  752.                         Instr = FindInstruction (&CurTok.SVal);
  753.                     }                
  754.                 } else {
  755.                     /* Macros and symbols may NOT use the names of instructions */
  756.                     Instr = FindInstruction (&CurTok.SVal);
  757.                     if (Instr < 0) {
  758.                         Mac = FindMacro (&CurTok.SVal);
  759.                     }
  760.                 }
  761.             }
  762.         }
  763.     }
  764.  
  765.     /* We've handled a possible label, now handle the remainder of the line */
  766.     if (CurTok.Tok >= TOK_FIRSTPSEUDO && CurTok.Tok <= TOK_LASTPSEUDO) {
  767.         /* A control command */
  768.         HandlePseudo ();
  769.     } else if (Mac != 0) {
  770.         /* A macro expansion */
  771.         MacExpandStart (Mac);
  772.     } else if (Instr >= 0 ||
  773.                (UbiquitousIdents && ((Instr = FindInstruction (&CurTok.SVal)) >= 0))) {
  774.         /* A mnemonic - assemble one instruction */
  775.         HandleInstruction (Instr);
  776.     } else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) {
  777.         NextTok ();
  778.         if (CurTok.Tok != TOK_EQ) {
  779.             Error ("`=' expected");
  780.             SkipUntilSep ();
  781.         } else {
  782.             /* Skip the equal sign */
  783.             NextTok ();
  784.             /* Enter absolute mode */
  785.             DoPCAssign ();
  786.         }
  787.     }
  788.  
  789.     /* If we have defined a label, remember its size. Sym is also set by
  790.      * a symbol assignment, but in this case Done is false, so we don't
  791.      * come here.
  792.      */
  793.     if (Sym) {
  794.         unsigned long Size;
  795.         if (Seg == ActiveSeg) {
  796.             /* Same segment */
  797.             Size = GetPC () - PC;
  798.         } else {
  799.             /* The line has switched the segment */
  800.             Size = 0;
  801.         }
  802.         DefSizeOfSymbol (Sym, Size);
  803.     }
  804.  
  805.     /* Line separator must come here */
  806.     ConsumeSep ();
  807. }
  808.  
  809.  
  810.  
  811. static void Assemble (void)
  812. /* Start the ball rolling ... */
  813. {
  814.     /* Prime the pump */
  815.     NextTok ();
  816.  
  817.     /* Assemble lines until end of file */
  818.     while (CurTok.Tok != TOK_EOF) {
  819.         OneLine ();
  820.     }
  821. }
  822.  
  823.  
  824.  
  825. static void CreateObjFile (void)
  826. /* Create the object file */
  827. {
  828.     /* Open the object, write the header */
  829.     ObjOpen ();
  830.  
  831.     /* Write the object file options */
  832.     WriteOptions ();
  833.  
  834.     /* Write the list of input files */
  835.     WriteFiles ();
  836.  
  837.     /* Write the segment data to the file */
  838.     WriteSegments ();
  839.  
  840.     /* Write the import list */
  841.     WriteImports ();
  842.  
  843.     /* Write the export list */
  844.     WriteExports ();
  845.  
  846.     /* Write debug symbols if requested */
  847.     WriteDbgSyms ();
  848.  
  849.     /* Write the scopes if requested */
  850.     WriteScopes ();
  851.  
  852.     /* Write line infos if requested */
  853.     WriteLineInfos ();
  854.  
  855.     /* Write the string pool */
  856.     WriteStrPool ();
  857.  
  858.     /* Write the assertions */
  859.     WriteAssertions ();
  860.  
  861.     /* Write the spans */
  862.     WriteSpans ();
  863.  
  864.     /* Write an updated header and close the file */
  865.     ObjClose ();
  866. }
  867.  
  868.  
  869.  
  870. int main (int argc, char* argv [])
  871. /* Assembler main program */
  872. {
  873.     /* Program long options */
  874.     static const LongOpt OptTab[] = {
  875.         { "--auto-import",      0,      OptAutoImport           },
  876.         { "--bin-include-dir",  1,      OptBinIncludeDir        },
  877.         { "--cpu",              1,      OptCPU                  },
  878.         { "--create-dep",       1,      OptCreateDep            },
  879.         { "--create-full-dep",  1,      OptCreateFullDep        },
  880.         { "--debug",            0,      OptDebug                },
  881.         { "--debug-info",       0,      OptDebugInfo            },
  882.         { "--feature",          1,      OptFeature              },
  883.         { "--help",             0,      OptHelp                 },
  884.         { "--ignore-case",      0,      OptIgnoreCase           },
  885.         { "--include-dir",      1,      OptIncludeDir           },
  886.         { "--large-alignment",  0,      OptLargeAlignment       },
  887.         { "--list-bytes",       1,      OptListBytes            },
  888.         { "--listing",          1,      OptListing              },
  889.         { "--memory-model",     1,      OptMemoryModel          },
  890.         { "--pagelength",       1,      OptPageLength           },
  891.         { "--relax-checks",     0,      OptRelaxChecks          },
  892.         { "--smart",            0,      OptSmart                },
  893.         { "--target",           1,      OptTarget               },
  894.         { "--verbose",          0,      OptVerbose              },
  895.         { "--version",          0,      OptVersion              },
  896.     };
  897.  
  898.     /* Name of the global name space */
  899.     static const StrBuf GlobalNameSpace = STATIC_STRBUF_INITIALIZER;
  900.  
  901.     unsigned I;
  902.  
  903.     /* Initialize the cmdline module */
  904.     InitCmdLine (&argc, &argv, "ca65");
  905.  
  906.     /* Initialize the string pool */
  907.     InitStrPool ();
  908.  
  909.     /* Initialize the include search paths */
  910.     InitIncludePaths ();
  911.  
  912.     /* Create the predefined segments */
  913.     SegInit ();
  914.  
  915.     /* Enter the base lexical level. We must do that here, since we may
  916.      * define symbols using -D.
  917.      */
  918.     SymEnterLevel (&GlobalNameSpace, SCOPE_FILE, ADDR_SIZE_DEFAULT, 0);
  919.  
  920.     /* Initialize the line infos. Must be done here, since we need line infos
  921.      * for symbol definitions.
  922.      */
  923.     InitLineInfo ();
  924.  
  925.     /* Check the parameters */
  926.     I = 1;
  927.     while (I < ArgCount) {
  928.  
  929.         /* Get the argument */
  930.         const char* Arg = ArgVec [I];
  931.  
  932.         /* Check for an option */
  933.         if (Arg[0] == '-') {
  934.             switch (Arg[1]) {
  935.  
  936.                 case '-':
  937.                     LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
  938.                     break;
  939.  
  940.                 case 'd':
  941.                     OptDebug (Arg, 0);
  942.                     break;
  943.  
  944.                 case 'g':
  945.                     OptDebugInfo (Arg, 0);
  946.                     break;
  947.  
  948.                 case 'h':
  949.                     OptHelp (Arg, 0);
  950.                     break;
  951.  
  952.                 case 'i':
  953.                     OptIgnoreCase (Arg, 0);
  954.                     break;
  955.  
  956.                 case 'l':
  957.                     OptListing (Arg, GetArg (&I, 2));
  958.                     break;
  959.  
  960.                 case 'm':
  961.                     if (Arg[2] == 'm') {
  962.                         OptMemoryModel (Arg, GetArg (&I, 3));
  963.                     } else {
  964.                         UnknownOption (Arg);
  965.                     }
  966.                     break;
  967.  
  968.                 case 'o':
  969.                     OutFile = GetArg (&I, 2);
  970.                     break;
  971.  
  972.                 case 's':
  973.                     OptSmart (Arg, 0);
  974.                     break;
  975.  
  976.                 case 't':
  977.                     OptTarget (Arg, GetArg (&I, 2));
  978.                     break;
  979.  
  980.                 case 'v':
  981.                     OptVerbose (Arg, 0);
  982.                     break;
  983.  
  984.                 case 'D':
  985.                     DefineSymbol (GetArg (&I, 2));
  986.                     break;
  987.  
  988.                 case 'I':
  989.                     OptIncludeDir (Arg, GetArg (&I, 2));
  990.                     break;
  991.  
  992.                 case 'U':
  993.                     OptAutoImport (Arg, 0);
  994.                     break;
  995.  
  996.                 case 'V':
  997.                     OptVersion (Arg, 0);
  998.                     break;
  999.  
  1000.                 case 'W':
  1001.                     WarnLevel = atoi (GetArg (&I, 2));
  1002.                     break;
  1003.  
  1004.                 default:
  1005.                     UnknownOption (Arg);
  1006.                     break;
  1007.  
  1008.             }
  1009.         } else {
  1010.             /* Filename. Check if we already had one */
  1011.             if (InFile) {
  1012.                 fprintf (stderr, "%s: Don't know what to do with `%s'\n",
  1013.                          ProgName, Arg);
  1014.                 exit (EXIT_FAILURE);
  1015.             } else {
  1016.                 InFile = Arg;
  1017.             }
  1018.         }
  1019.  
  1020.         /* Next argument */
  1021.         ++I;
  1022.     }
  1023.  
  1024.     /* Do we have an input file? */
  1025.     if (InFile == 0) {
  1026.         fprintf (stderr, "%s: No input files\n", ProgName);
  1027.         exit (EXIT_FAILURE);
  1028.     }
  1029.  
  1030.     /* Add the default include search paths. */
  1031.     FinishIncludePaths ();
  1032.  
  1033.     /* If no CPU given, use the default CPU for the target */
  1034.     if (GetCPU () == CPU_UNKNOWN) {
  1035.         if (Target != TGT_UNKNOWN) {
  1036.             SetCPU (GetTargetProperties (Target)->DefaultCPU);
  1037.         } else {
  1038.             SetCPU (CPU_6502);
  1039.         }
  1040.     }
  1041.  
  1042.     /* If no memory model was given, use the default */
  1043.     if (MemoryModel == MMODEL_UNKNOWN) {
  1044.         SetMemoryModel (MMODEL_NEAR);
  1045.     }
  1046.  
  1047.     /* Set the default segment sizes according to the memory model */
  1048.     SetSegmentSizes ();
  1049.  
  1050.     /* Initialize the scanner, open the input file */
  1051.     InitScanner (InFile);
  1052.  
  1053.     /* Define the default options */
  1054.     SetOptions ();
  1055.  
  1056.     /* Assemble the input */
  1057.     Assemble ();
  1058.  
  1059.     /* If we didn't have any errors, check the pseudo insn stacks */
  1060.     if (ErrorCount == 0) {
  1061.         CheckPseudo ();
  1062.     }
  1063.  
  1064.     /* If we didn't have any errors, check and cleanup the unnamed labels */
  1065.     if (ErrorCount == 0) {
  1066.         ULabDone ();
  1067.     }
  1068.  
  1069.     /* If we didn't have any errors, check the symbol table */
  1070.     if (ErrorCount == 0) {
  1071.         SymCheck ();
  1072.     }
  1073.  
  1074.     /* If we didn't have any errors, check the hll debug symbols */
  1075.     if (ErrorCount == 0) {
  1076.         DbgInfoCheck ();
  1077.     }
  1078.  
  1079.     /* If we didn't have any errors, close the file scope lexical level */
  1080.     if (ErrorCount == 0) {
  1081.         SymLeaveLevel ();
  1082.     }
  1083.  
  1084.     /* If we didn't have any errors, check and resolve the segment data */
  1085.     if (ErrorCount == 0) {
  1086.         SegDone ();
  1087.     }
  1088.  
  1089.     /* If we didn't have any errors, check the assertions */
  1090.     if (ErrorCount == 0) {
  1091.         CheckAssertions ();
  1092.     }
  1093.  
  1094.     /* Dump the data */
  1095.     if (Verbosity >= 2) {
  1096.         SymDump (stdout);
  1097.         SegDump ();
  1098.     }
  1099.  
  1100.     /* If we didn't have an errors, finish off the line infos */
  1101.     DoneLineInfo ();
  1102.  
  1103.     /* If we didn't have any errors, create the object, listing and
  1104.      * dependency files
  1105.      */
  1106.     if (ErrorCount == 0) {
  1107.         CreateObjFile ();
  1108.         if (SB_GetLen (&ListingName) > 0) {
  1109.             CreateListing ();
  1110.         }
  1111.        CreateDependencies ();
  1112.     }
  1113.  
  1114.     /* Close the input file */
  1115.     DoneScanner ();
  1116.  
  1117.     /* Return an apropriate exit code */
  1118.     return (ErrorCount == 0)? EXIT_SUCCESS : EXIT_FAILURE;
  1119. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement