Annotation of nono/util/iasm/iasm.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // XM6i
        !             3: // Copyright (C) 2012-2016 [email protected]
        !             4: //
        !             5: // 簡易アセンブラ
        !             6: //
        !             7: 
        !             8: #include <stdio.h>
        !             9: #include <stdint.h>
        !            10: #include <stdlib.h>
        !            11: #include <stdarg.h>
        !            12: #include <string.h>
        !            13: #include <unistd.h>
        !            14: #include <map>
        !            15: #include <stack>
        !            16: #include <vector>
        !            17: #include "iasm.h"
        !            18: 
        !            19: // OSX で iconv はちょっと置いておく
        !            20: #if !defined(__APPLE__)
        !            21: #define IASM_USE_iconv
        !            22: #endif
        !            23: 
        !            24: #if defined(IASM_USE_iconv)
        !            25: #include <iconv.h>
        !            26: #elif defined(IASM_USE_wxWidgets)
        !            27: #include <wx/wx.h>
        !            28: #include <wx/strconv.h>
        !            29: #endif
        !            30: 
        !            31: /*
        !            32:  * iconv(3) の第2引数は本来は char** だが (Linux)、
        !            33:  * 歴史的経緯により const char** な環境もある (NetBSD、FreeBSD)。
        !            34:  */
        !            35: #if defined(IASM_ICONV_CONST)
        !            36: typedef const char **iconv_src_t;
        !            37: #else
        !            38: typedef char **iconv_src_t;
        !            39: #endif
        !            40: 
        !            41: #define BUFSIZE        (1024)
        !            42: 
        !            43: #define D_INOUT        (0x0001)        /* 入出力のみ */
        !            44: #define D_EA   (0x0002)        /* EA のみ */
        !            45: #define D_LABEL        (0x0004)        /* ラベル関係 */
        !            46: #define D_PARSE        (0x0008)        /* パーサ */
        !            47: #define D_EXPR (0x0010)        /* 式 */
        !            48: #define D_SCAN (0x0020)        /* スキャナ */
        !            49: #define D_STAGE        (0x8000)        /* ステージ */
        !            50: 
        !            51: typedef std::vector<String> ArrayString;
        !            52: typedef std::map<String, String> LabelHash;
        !            53: typedef void (opfunc_t)(uint16_t);
        !            54: typedef std::vector<Token> ArrayToken;
        !            55: 
        !            56: /* オペランド形式 */
        !            57: enum oprand_type_t {
        !            58:        OPR_EA = 0,                     /* 最大2つのEA (命令用) */
        !            59:        OPR_LIST,                       /* カンマ区切りリスト */
        !            60:        OPR_LITERAL,            /* 1つのリテラル */
        !            61: };
        !            62: 
        !            63: /* 命令処理分岐テーブル */
        !            64: struct optable_t {
        !            65:        const char *opname;             /* 命令語(完全一致) */
        !            66:        opfunc_t *func;                 /* 処理関数 */
        !            67:        uint16_t opword;                /* 命令ワード */
        !            68:        oprand_type_t oprand_type;      /* オペランド形式 */
        !            69: };
        !            70: 
        !            71: /* EA タイプ */
        !            72: enum eatype_t {
        !            73:        EAT_Dn          = 0x0001,
        !            74:        EAT_An          = 0x0002,
        !            75:        EAT_AI          = 0x0004,
        !            76:        EAT_API         = 0x0008,
        !            77:        EAT_APD         = 0x0010,
        !            78:        EAT_AREL        = 0x0020,
        !            79:        EAT_ABS         = 0x0040,
        !            80:        EAT_PCREL       = 0x0080,
        !            81:        EAT_IMM         = 0x0100,
        !            82: 
        !            83:        EAT_ALL         = 0x01ff,
        !            84:        EAT_DATA        = (EAT_ALL & ~EAT_An),
        !            85:        EAT_CNTL        = (EAT_An | EAT_AREL | EAT_ABS | EAT_PCREL),
        !            86: };
        !            87: 
        !            88: /* EA */
        !            89: enum eamode_t {
        !            90:        EA_Dn           = 0x00,
        !            91:        EA_An           = 0x08,
        !            92:        EA_An_I         = 0x10,
        !            93:        EA_An_PI        = 0x18,
        !            94:        EA_An_PD        = 0x20,
        !            95:        EA_d16An        = 0x28,
        !            96:        EA_d8AnIX       = 0x30,
        !            97:        EA_ABS_W        = 0x38,
        !            98:        EA_ABS_L        = 0x39,
        !            99:        EA_d16PC        = 0x3a,
        !           100:        EA_d8PCIX       = 0x3b,
        !           101:        EA_IMMEDIATE = 0x3c,
        !           102: };
        !           103: 
        !           104: class EA {
        !           105:  public:
        !           106:        int mode;               /* 種別 */
        !           107:        uint32_t val;   /* 値。ABS か #imm の場合に使用 */
        !           108:        int size;               /* サイズ(バイト数)。#imm の場合に使用 */
        !           109:        String label;   /* あれば未解決ラベル。空文字列なら val を使用のこと */
        !           110: 
        !           111:        EA() {
        !           112:                mode = 0;
        !           113:                val = 0;
        !           114:                size = 0;
        !           115:        }
        !           116:        int type() const { return (mode >> 3) & 7; };
        !           117:        int num()  const { return (mode & 7); };
        !           118: };
        !           119: 
        !           120: /* 参照種別 */
        !           121: enum reftype_t {
        !           122:        REFTYPE_BYTE,
        !           123:        REFTYPE_WORD,
        !           124:        REFTYPE_LONG,
        !           125: };
        !           126: 
        !           127: /* 後から参照(式)を解決するための構造体 */
        !           128: struct REF {
        !           129:        int pos;                        /* 出力位置 */
        !           130:        int line;                       /* 現在の行数 */
        !           131:        reftype_t type;         /* 種別(サイズ) */
        !           132:        ArrayString expr;       /* 中間式 */
        !           133: };
        !           134: typedef std::vector<REF*> ArrayRef;
        !           135: 
        !           136: /* サイズサフィックスから bit7-6 がサイズを示すやつ用に変換 */
        !           137: const uint16_t size6[] = {
        !           138:        0,
        !           139:        0x0000, /* 1=.B */
        !           140:        0x0040, /* 2=.W */
        !           141:        0,
        !           142:        0x0080, /* 4=.L */
        !           143: };
        !           144: 
        !           145: /* 出力形式 */
        !           146: enum format_t {
        !           147:        FORMAT_C,                       /* C ソース */
        !           148:        FORMAT_BINARY,          /* バイナリ */
        !           149: };
        !           150: 
        !           151: const char *outfile;           /* 出力ファイル名 */
        !           152: FILE *outfp;                           /* 出力ファイル */
        !           153: int debug;                                     /* デバッグモード */
        !           154: const char *current_infile;    /* 現在の入力ファイル名 */
        !           155: int line;                                      /* 現在のファイル中の行数(エラー表示用) */
        !           156: format_t format;                       /* 出力形式 */
        !           157: uint32_t origin;                       /* 現在のブロックの開始アドレス */
        !           158: uint32_t pc;                           /* 現在の PC */
        !           159: String label0;                         /* 現在行のラベル */
        !           160: String op0;                                    /* 現在の命令語 */
        !           161: String size0;                          /* 現在のサイズサフィックス (文字) */
        !           162: int size_sfx;                          /* 現在のサイズサフィックス (B=1/W=2/L=4) */
        !           163: ArrayString oprand;                    /* 現在のオペランド */
        !           164: String current_name;           /* .start で指示された変数名 */
        !           165: String outbin;                         /* 現在出力しているバイナリ列 */
        !           166: LabelHash label_list;          /* ラベルのリスト */
        !           167: ArrayRef ref_list;                     /* ラベルを参照する側のリスト */
        !           168: int rept_start;                                /* .rept 開始位置 */
        !           169: int rept_count;                                /* .rept 回数 */
        !           170: 
        !           171: void usage(const char *) __attribute__((__noreturn__));
        !           172: int asm_main(const char *);
        !           173: void parse_asm(String&);
        !           174: void scan_asm(String&, ArrayToken&);
        !           175: void parse_token(ArrayToken&);
        !           176: void parse_arg_literal(ArrayToken&, ArrayToken::iterator&);
        !           177: void parse_arg_list(ArrayToken&, ArrayToken::iterator&);
        !           178: void parse_arg_ea(ArrayToken&, ArrayToken::iterator&);
        !           179: void include_iocs();
        !           180: void add_label(String&);
        !           181: bool find_label(String&, uint32_t&);
        !           182: optable_t *lookup(String&);
        !           183: void format_c();
        !           184: void format_binary();
        !           185: bool try_ea(String&, EA&, String&, int);
        !           186: EA get_ea(String&);
        !           187: EA get_ea(String&, int);
        !           188: bool get_reglist(String&, uint16_t&);
        !           189: int get_cc(String&);
        !           190: void output_ea(EA&);
        !           191: void add_ref(reftype_t, String&);
        !           192: void output_bin(uint32_t, int);
        !           193: void output_b(uint32_t);
        !           194: void output_w(uint32_t);
        !           195: void output_l(uint32_t);
        !           196: void output_ds(int);
        !           197: String num2str(int);
        !           198: String num2hex(int);
        !           199: bool parse_number(String&, int*);
        !           200: int tonumber(String&);
        !           201: bool parse_expr(String&, ArrayString&);
        !           202: bool scan_expr(String&, ArrayString&);
        !           203: void add_expr(int pos, reftype_t, ArrayString&);
        !           204: String parse_string(String&);
        !           205: String convert_charset(String&);
        !           206: void DPRINTN_ref(int, REF *);
        !           207: void DPRINTN_expr(int, ArrayString&);
        !           208: bool calc_expr(ArrayString&, uint32_t&, bool);
        !           209: void DPRINTV(int, const char *, va_list);
        !           210: void DPRINTN(int, const char *, ...);
        !           211: void DPRINTF(int, const char *, ...);
        !           212: void error(const char *, ...) __attribute__((__noreturn__)); /* エラー出力 */
        !           213: void trim(String&);                                    /* 前後の空白を取り除く */
        !           214: void ltrim(String&);                           /* 先頭の空白を取り除く */
        !           215: void rtrim(String&);                           /* 末尾の空白を取り除く */
        !           216: 
        !           217: opfunc_t op_cinclude;
        !           218: opfunc_t op_org;
        !           219: opfunc_t op_start;
        !           220: opfunc_t op_end;
        !           221: opfunc_t op_dc;
        !           222: opfunc_t op_ds;
        !           223: opfunc_t op_even;
        !           224: opfunc_t op_equ;
        !           225: opfunc_t op_rept;
        !           226: opfunc_t op_endrept;
        !           227: opfunc_t op_iocs;
        !           228: opfunc_t op_bcc;
        !           229: opfunc_t op_bra;
        !           230: opfunc_t op_clr;
        !           231: opfunc_t op_dbra;
        !           232: opfunc_t op_jmp;
        !           233: opfunc_t op_lea;
        !           234: opfunc_t op_move;
        !           235: opfunc_t op_movem;
        !           236: opfunc_t op_moveq;
        !           237: opfunc_t op_sub;
        !           238: opfunc_t op_suba;
        !           239: opfunc_t op_trap;
        !           240: opfunc_t op_noarg;
        !           241: 
        !           242: optable_t optable[] = {
        !           243:        { ".cinclude",  op_cinclude,    0,      OPR_LITERAL, },
        !           244:        { ".org",               op_org,                 0,      OPR_LIST, },
        !           245:        { ".start",             op_start,               0,      OPR_LITERAL, },
        !           246:        { ".end",               op_end,                 0,      OPR_LIST, },
        !           247:        { ".dc",                op_dc,                  0,      OPR_LIST, },
        !           248:        { ".ds",                op_ds,                  0,      OPR_LIST, },
        !           249:        { ".even",              op_even,                0,      OPR_LIST, },
        !           250:        { ".equ",               op_equ,                 0,      OPR_LIST, },
        !           251:        { ".rept",              op_rept,                0,      OPR_LIST, },
        !           252:        { ".endrept",   op_endrept,             0,      OPR_LIST, },
        !           253: 
        !           254:        /* マクロが定義できないのでここでやっちまう */
        !           255:        { "IOCS",               op_iocs, },
        !           256: 
        !           257:        /* XXX BCC.B <cond>,<label> */
        !           258:        { "bcc",                op_bcc,         0x6000, },
        !           259: 
        !           260:        { "bra",                op_bra,         0x6000, },
        !           261:        { "clr",                op_clr,         0x4200, },
        !           262:        { "dbra",               op_dbra,        0x51c8, },
        !           263:        { "jmp",                op_jmp,         0x4ec0, },
        !           264:        { "lea",                op_lea,         0x41c0, },
        !           265:        { "move",               op_move,        0x0000, },
        !           266:        { "movem",              op_movem,       0x4880, },
        !           267:        { "moveq",              op_moveq,       0x7000, },
        !           268:        { "sub",                op_sub,         0x9000, },
        !           269:        { "suba",               op_suba,        0x90c0, },
        !           270:        { "trap",               op_trap,        0x4e40, },
        !           271: 
        !           272:        /* オペランドのないやつ */
        !           273:        { "reset",              op_noarg,       0x4e70, },
        !           274:        { "nop",                op_noarg,       0x4e71, },
        !           275:        { "rte",                op_noarg,       0x4e73, },
        !           276:        { "rtd",                op_noarg,       0x4e74, },
        !           277:        { "rts",                op_noarg,       0x4e75, },
        !           278:        { "trapv",              op_noarg,       0x4e76, },
        !           279:        { "rtr",                op_noarg,       0x4e77, },
        !           280: 
        !           281:        { NULL, NULL, },
        !           282: };
        !           283: 
        !           284: const char *regname[] = {
        !           285:        "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
        !           286:        "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
        !           287:        "(A0)",  "(A1)",  "(A2)",  "(A3)",  "(A4)",  "(A5)",  "(A6)",  "(A7)",
        !           288:        "(A0)+", "(A1)+", "(A2)+", "(A3)+", "(A4)+", "(A5)+", "(A6)+", "(A7)+",
        !           289:        "-(A0)", "-(A1)", "-(A2)", "-(A3)", "-(A4)", "-(A5)", "-(A6)", "-(A7)",
        !           290: };
        !           291: 
        !           292: const char *ccname[] = {
        !           293:        "t",  "f",  "hi", "ls", "cc", "cs", "ne", "eq",
        !           294:        "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le",
        !           295: };
        !           296: 
        !           297: const char *iocscall[] = {
        !           298:        "_B_KEYINP",    // $00
        !           299:        "_B_KEYSNS",    // $01
        !           300:        "_B_SFTSNS",    // $02
        !           301:        "_KEY_INIT",    // $03
        !           302:        "_BITSNS",              // $04
        !           303:        "_SKEYSET",             // $05
        !           304:        "_LEDCTRL",             // $06
        !           305:        "_LEDSET",              // $07
        !           306:        "_KEYDLY",              // $08
        !           307:        "_KEYREP",              // $09
        !           308:        "$0a",                  // $0a
        !           309:        "$0b",                  // $0b
        !           310:        "_TVCTRL",              // $0c
        !           311:        "_LEDMOD",              // $0d
        !           312:        "_TGUSEMD",             // $0e
        !           313:        "_DEFCHR",              // $0f
        !           314:        "_CRTMOD",              // $10
        !           315:        "_CONTRAST",    // $11
        !           316:        "_HSVTORGB",    // $12
        !           317:        "_TPALET",              // $13
        !           318:        "_TPALET2",             // $14
        !           319:        "_TCOLOR",              // $15
        !           320:        "_FNTADR",              // $16
        !           321:        "_VRAMGET",             // $17
        !           322:        "_VRAMPUT",             // $18
        !           323:        "_FNTGET",              // $19
        !           324:        "_TEXTGET",             // $1a
        !           325:        "_TEXTPUT",             // $1b
        !           326:        "_CLIPPUT",             // $1c
        !           327:        "_SCROLL",              // $1d
        !           328:        "_B_CURON",             // $1e
        !           329:        "_B_CUROFF",    // $1f
        !           330:        "_B_PUTC",              // $20
        !           331:        "_B_PRINT",             // $21
        !           332:        "_B_COLOR",             // $22
        !           333:        "_B_LOCATE",    // $23
        !           334:        "_B_DOWN_S",    // $24
        !           335:        "_B_UP_S",              // $25
        !           336:        "_B_UP",                // $26
        !           337:        "_B_DOWN",              // $27
        !           338:        "_B_RIGHT",             // $28
        !           339:        "_B_LEFT",              // $29
        !           340:        "_B_CLR_ST",    // $2a
        !           341:        "_B_ERA_ST",    // $2b
        !           342:        "_B_INS",               // $2c
        !           343:        "_B_DEL",               // $2d
        !           344:        "_B_CONSOL",    // $2e
        !           345:        "_B_PUTMES",    // $2f
        !           346:        "_SET232C",             // $30
        !           347:        "_LOF232C",             // $31
        !           348:        "_INP232C",             // $32
        !           349:        "_ISNS232C",    // $33
        !           350:        "_OSNS232C",    // $34
        !           351:        "_OUT232C",             // $35
        !           352:        "$36",                  // $36
        !           353:        "$37",                  // $37
        !           354:        "_SETFNTADR",   // $38
        !           355:        "$39",                  // $39
        !           356:        "$3a",                  // $3a
        !           357:        "_JOYGET",              // $3b
        !           358:        "_INIT_PRN",    // $3c
        !           359:        "_SNSPRN",              // $3d
        !           360:        "_OUTLPT",              // $3e
        !           361:        "_OUTPRN",              // $3f
        !           362:        "_B_SEEK",              // $40
        !           363:        "_B_VERIFY",    // $41
        !           364:        "_B_READDI",    // $42
        !           365:        "_B_DSKINI",    // $43
        !           366:        "_B_DRVSNS",    // $44
        !           367:        "_B_WRITE",             // $45
        !           368:        "_B_READ",              // $46
        !           369:        "_B_RECALI",    // $47
        !           370:        "_B_ASSIGN",    // $48
        !           371:        "_B_WRITED",    // $49
        !           372:        "_B_READID",    // $4a
        !           373:        "_B_BADFMT",    // $4b
        !           374:        "_B_READDL",    // $4c
        !           375:        "_B_FORMAT",    // $4d
        !           376:        "_B_DRVCHK",    // $4e
        !           377:        "_B_EJECT",             // $4f
        !           378:        "_DATEBCD",             // $50
        !           379:        "_DATESET",             // $51
        !           380:        "_TIMEBCD",             // $52
        !           381:        "_TIMESET",             // $53
        !           382:        "_DATEGET",             // $54
        !           383:        "_DATEBIN",             // $55
        !           384:        "_TIMEGET",             // $56
        !           385:        "_TIMEBIN",             // $57
        !           386:        "_DATECNV",             // $58
        !           387:        "_TIMECNV",             // $59
        !           388:        "_DATEASC",             // $5a
        !           389:        "_TIMEASC",             // $5b
        !           390:        "_DAYASC",              // $5c
        !           391:        "_ALARMMOD",    // $5d
        !           392:        "_ALARMSET",    // $5e
        !           393:        "_ALARMGET",    // $5f
        !           394:        "_ADPCMOUT",    // $60
        !           395:        "_ADPCMINP",    // $61
        !           396:        "_ADPCMAOT",    // $62
        !           397:        "_ADPCMAIN",    // $63
        !           398:        "_ADPCMLOT",    // $64
        !           399:        "_ADPCMLIN",    // $65
        !           400:        "_ADPCMSNS",    // $66
        !           401:        "_ADPCMMOD",    // $67
        !           402:        "_OPMSET",              // $68
        !           403:        "_OPMSNS",              // $69
        !           404:        "_OPMINTST",    // $6a
        !           405:        "_TIMERDST",    // $6b
        !           406:        "_VDISPST",             // $6c
        !           407:        "_CRTCRAS",             // $6d
        !           408:        "_HSYNCST",             // $6e
        !           409:        "_PRNINTST",    // $6f
        !           410:        "_MS_INIT",             // $70
        !           411:        "_MS_CURON",    // $71
        !           412:        "_MS_CUROF",    // $72
        !           413:        "_MS_STAT",             // $73
        !           414:        "_MS_GETDT",    // $74
        !           415:        "_MS_CURGT",    // $75
        !           416:        "_MS_CURST",    // $76
        !           417:        "_MS_LIMIT",    // $77
        !           418:        "_MS_OFFTM",    // $78
        !           419:        "_MS_ONTM",             // $79
        !           420:        "_MS_PATST",    // $7a
        !           421:        "_MS_SEL",              // $7b
        !           422:        "_MS_SEL2",             // $7c
        !           423:        "_SKEY_MOD",    // $7d
        !           424:        "_DENSNS",              // $7e
        !           425:        "_ONTIME",              // $7f
        !           426:        "_B_INTVCS",    // $80
        !           427:        "_B_SUPER",             // $81
        !           428:        "_B_BPEEK",             // $82
        !           429:        "_B_WPEEK",             // $83
        !           430:        "_B_LPEEK",             // $84
        !           431:        "_B_MEMSTR",    // $85
        !           432:        "_B_BPOKE",             // $86
        !           433:        "_B_WPOKE",             // $87
        !           434:        "_B_LPOKE",             // $88
        !           435:        "_B_MEMSET",    // $89
        !           436:        "_DMAMOVE",             // $8a
        !           437:        "_DMAMOV_A",    // $8b
        !           438:        "_DMAMOV_L",    // $8c
        !           439:        "_DMAMODE",             // $8d
        !           440:        "_BOOTINF",             // $8e
        !           441:        "_ROMVER",              // $8f
        !           442:        "_G_CLR_ON",    // $90
        !           443:        "$91",                  // $91
        !           444:        "$92",                  // $92
        !           445:        "$93",                  // $93
        !           446:        "_GPALET",              // $94
        !           447:        "$95",                  // $95
        !           448:        "$96",                  // $96
        !           449:        "$97",                  // $97
        !           450:        "$98",                  // $98
        !           451:        "$99",                  // $99
        !           452:        "$9a",                  // $9a
        !           453:        "$9b",                  // $9b
        !           454:        "$9c",                  // $9c
        !           455:        "", "", "",
        !           456:        "_SFTJIS",              // $a0
        !           457:        "_JISSFT",              // $a1
        !           458:        "_AKCONV",              // $a2
        !           459:        "_RMACNV",              // $a3
        !           460:        "_DAKJOB",              // $a4
        !           461:        "_HANJOB",              // $a5
        !           462:        "", "", "",
        !           463:        "", "", "",
        !           464:        "_SYS_STAT",    // $ac
        !           465:        "_B_CONMOD",    // $ad
        !           466:        "_OS_CURON",    // $ae
        !           467:        "_OS_CUROF",    // $af
        !           468:        "_DRAWMODE",    // $b0
        !           469:        "_APAGE",               // $b1
        !           470:        "_VPAGE",               // $b2
        !           471:        "_HOME",                // $b3
        !           472:        "_WINDOW",              // $b4
        !           473:        "_WIPE",                // $b5
        !           474:        "_PSET",                // $b6
        !           475:        "_POINT",               // $b7
        !           476:        "_LINE",                // $b8
        !           477:        "_BOX",                 // $b9
        !           478:        "_FILL",                // $ba
        !           479:        "_CIRCLE",              // $bb
        !           480:        "_PAINT",               // $bc
        !           481:        "_SYMBOL",              // $bd
        !           482:        "_GETGRM",              // $be
        !           483:        "_PUTGRM",              // $bf
        !           484:        "_SP_INIT",             // $c0
        !           485:        "_SP_ON",               // $c1
        !           486:        "_SP_OFF",              // $c2
        !           487:        "_SP_CGCLR",    // $c3
        !           488:        "_SP_DEFCG",    // $c4
        !           489:        "_SP_GTPCG",    // $c5
        !           490:        "_SP_REGST",    // $c6
        !           491:        "_SP_REGGT",    // $c7
        !           492:        "_BGSCRLST",    // $c8
        !           493:        "_BGSCRLGT",    // $c9
        !           494:        "_BGCTRLST",    // $ca
        !           495:        "_BGCTRLGT",    // $cb
        !           496:        "_BGTEXTCL",    // $cc
        !           497:        "_BGTEXTST",    // $cd
        !           498:        "_BGTEXTGT",    // $ce
        !           499:        "_SPALET",              // $cf
        !           500:        "", "", "",
        !           501:        "_TXXLINE",             // $d3
        !           502:        "_TXYLINE",             // $d4
        !           503:        "_TXLINE",              // $d5
        !           504:        "_TXBOX",               // $d6
        !           505:        "_TXFILL",              // $d7
        !           506:        "_TXREV",               // $d8
        !           507:        "", "", "",
        !           508:        "", "", "",
        !           509:        "_TXRASCPY",    // $df
        !           510:        "", "", "", "",
        !           511:        "", "", "", "",
        !           512:        "", "", "", "",
        !           513:        "", "", "", "",
        !           514:        "_OPMDRV",              // $f0
        !           515:        "_RSDRV",               // $f1
        !           516:        "_A_JOYGET",    // $f2
        !           517:        "_MUSICDRV",    // $f3
        !           518:        "",
        !           519:        "_SCSIDRV",             // $f5
        !           520:        "", "", "", "",
        !           521:        "", "", "",
        !           522:        "_ABORTRST",    // $fd
        !           523:        "_IPLERR",              // $fe
        !           524:        "_ABORTJOB",    // $ff
        !           525: };
        !           526: 
        !           527: void
        !           528: usage(const char *progname)
        !           529: {
        !           530: #if defined(_WIN32)
        !           531:        const char *conv = "Win32";
        !           532: #elif defined(IASM_USE_iconv)
        !           533:        const char *conv = "iconv";
        !           534: #elif defined(IASM_USE_wxWidgets)
        !           535:        const char *conv = "wxWidgets";
        !           536: #else
        !           537:        const char *conv = "none";
        !           538: #endif
        !           539: 
        !           540:        fprintf(stderr, "usage: %s [-d] [-f <fmt>] <infile> [<outfile>]\n",
        !           541:                progname);
        !           542:        fprintf(stderr, "  -f <fmt>   output format: c, binary\n");
        !           543:        fprintf(stderr, "compile option: charset conversion '%s'\n", conv);
        !           544:        exit(1);
        !           545: }
        !           546: 
        !           547: int
        !           548: main(int ac, char *av[])
        !           549: {
        !           550:        const char *progname;
        !           551:        const char *infile;
        !           552:        int c;
        !           553: 
        !           554:        progname = av[0];
        !           555:        while ((c = getopt(ac, av, "d:f:")) != -1) {
        !           556:                switch (c) {
        !           557:                 case 'd':
        !           558:                        debug = strtol(optarg, NULL, 16);
        !           559:                        break;
        !           560:                 case 'f':
        !           561:                        if (strcasecmp(optarg, "c") == 0) {
        !           562:                                format = FORMAT_C;
        !           563:                        } else if (strcasecmp(optarg, "binary") == 0) {
        !           564:                                format = FORMAT_BINARY;
        !           565:                        } else {
        !           566:                                usage(progname);
        !           567:                        }
        !           568:                        break;
        !           569:                 default:
        !           570:                        usage(progname);
        !           571:                        break;
        !           572:                }
        !           573:        }
        !           574:        ac -= optind;
        !           575:        av += optind;
        !           576: 
        !           577:        /* デバッグ指定が1つでもあれば STAGE を必ず有効にする */
        !           578:        if (debug > 0) {
        !           579:                debug |= D_STAGE;
        !           580:        }
        !           581: 
        !           582:        if (ac < 1) {
        !           583:                usage(progname);
        !           584:        }
        !           585:        infile = av[0];
        !           586: 
        !           587:        if (ac > 1) {
        !           588:                outfile = av[1];
        !           589:                outfp = fopen(outfile, "wb");
        !           590:                if (outfp == NULL) {
        !           591:                        fprintf(stderr, "cannot open outfile: %s\n", outfile);
        !           592:                        exit(1);
        !           593:                }
        !           594:        } else {
        !           595:                outfile = NULL;
        !           596:                outfp = stdout;
        !           597:        }
        !           598: 
        !           599:        /* IOCS コールマクロを定義 */
        !           600:        include_iocs();
        !           601: 
        !           602:        /* メイン処理 */
        !           603:        asm_main(infile);
        !           604: 
        !           605:        if (outfp != stdout) {
        !           606:                fclose(outfp);
        !           607:        }
        !           608: }
        !           609: 
        !           610: int
        !           611: asm_main(const char *infile)
        !           612: {
        !           613:        FILE *fp;
        !           614:        char cbuf[1024];
        !           615: 
        !           616:        /* ファイルオープン */
        !           617:        fp = fopen(infile, "r");
        !           618:        if (fp == NULL) {
        !           619:                fprintf(stderr, "cannot open %s", infile);
        !           620:                exit(1);
        !           621:        }
        !           622:        current_infile = infile;
        !           623: 
        !           624:        /* 1st ステージ: 読み込みながら処理 */
        !           625:        line = 0;
        !           626:        while (fgets(cbuf, sizeof(cbuf), fp)) {
        !           627:                String buf(cbuf);
        !           628:                line++;
        !           629: 
        !           630:                rtrim(buf);
        !           631:                DPRINTF(D_INOUT, "line %3d |%s|\n", ::line, buf.c_str());
        !           632: 
        !           633:                /* 1命令処理 */
        !           634:                parse_asm(buf);
        !           635:        }
        !           636: 
        !           637:        fclose(fp);
        !           638:        return 0;
        !           639: }
        !           640: 
        !           641: /* 1命令処理 */
        !           642: void
        !           643: parse_asm(String& buf)
        !           644: {
        !           645:        ArrayToken token_list;
        !           646: 
        !           647:        /* 字句解析 */
        !           648:        scan_asm(buf, token_list);
        !           649: 
        !           650:        /* 構文解析(?)して分岐 */
        !           651:        parse_token(token_list);
        !           652: }
        !           653: 
        !           654: /* 入力の1行 src を字句解析して結果を token_list に返す */
        !           655: void
        !           656: scan_asm(String& src, ArrayToken& token_list)
        !           657: {
        !           658:        Scanner s(src);
        !           659: 
        !           660:        for (;;) {
        !           661:                Token t;
        !           662: 
        !           663:                if (!s.get_token(t)) {
        !           664:                        error("syntax error: %s", s.errmsg.c_str());
        !           665:                }
        !           666: 
        !           667:                token_list.push_back(t);
        !           668: 
        !           669:                if (t.type == T_END) {
        !           670:                        break;
        !           671:                }
        !           672:        }
        !           673: 
        !           674:        /* 行末(T_ENDの前)が空白なら削除 */
        !           675:        if (token_list.size() > 1) {
        !           676:                ArrayToken::iterator it = token_list.end();
        !           677:                advance(it, -2);
        !           678:                if ((*it).type == T_SPACE) {
        !           679:                        token_list.erase(it);
        !           680:                }
        !           681:        }
        !           682: 
        !           683:        if ((debug & D_SCAN)) {
        !           684:                for (int i = 0; i < token_list.size(); i++) {
        !           685:                        Token t = token_list[i];
        !           686: 
        !           687:                        DPRINTF(D_SCAN, " %-7s |%s|", t.type_name(), t.word.c_str());
        !           688:                        if (t.type == T_NUMBER || t.type == T_SIZE || t.type == T_CHAR) {
        !           689:                                DPRINTN(D_SCAN, " num=$%x", t.number);
        !           690:                        }
        !           691:                        DPRINTN(D_SCAN, "\n");
        !           692:                }
        !           693:        }
        !           694: }
        !           695: 
        !           696: /* トークン列をパースして処理する */
        !           697: void
        !           698: parse_token(ArrayToken& list)
        !           699: {
        !           700:        ArrayToken::iterator t;
        !           701: 
        !           702:        /* 命令処理前にグローバル変数をクリア */
        !           703:        label0.erase();
        !           704:        op0.erase();
        !           705:        size0.erase();
        !           706:        size_sfx = -1;
        !           707:        oprand.clear();
        !           708: 
        !           709:        /* 先頭がリテラルならラベル */
        !           710:        t = list.begin();
        !           711:        if ((*t).type == T_LITERAL) {
        !           712:                /* ラベルをリストに記憶 */
        !           713:                DPRINTF(D_PARSE, "label='%s'\n", (*t).word.c_str());
        !           714:                label0 = (*t).word;
        !           715:                add_label(label0);
        !           716:                t++;
        !           717: 
        !           718:                /* 直後がコロンならスペースに置き換えてから */
        !           719:                if ((*t).type == T_COLON) {
        !           720:                        (*t).type = T_SPACE;
        !           721:                        t++;
        !           722:                }
        !           723:        }
        !           724: 
        !           725:        /* ラベルのみならここで終わり */
        !           726:        if ((*t).type == T_END) {
        !           727:                return;
        !           728:        }
        !           729:        /* そうでなければスペースのはずなので読み飛ばす */
        !           730:        if ((*t).type == T_SPACE) {
        !           731:                t++;
        !           732:        }
        !           733: 
        !           734:        /* 命令語は必ずリテラルから始まっている */
        !           735:        if ((*t).type != T_LITERAL) {
        !           736:                error("syntax error: invalid opword: %s\n", (*t).word.c_str());
        !           737:        }
        !           738:        /* 命令語を取り出す */
        !           739:        op0 = (*t).word;
        !           740:        t++;
        !           741: 
        !           742:        /* 直後がサイズサフィックスなら記憶 */
        !           743:        if ((*t).type == T_SIZE) {
        !           744:                size0 = (*t).word;
        !           745:                size_sfx = (*t).number;
        !           746:                t++;
        !           747:        }
        !           748:        DPRINTF(D_PARSE, "op0='%s' %s(%d)\n",
        !           749:                op0.c_str(), size0.c_str(), size_sfx);
        !           750: 
        !           751:        /* オペランドなしならここで終わり。ありなら空白のはず */
        !           752:        if ((*t).type == T_END) {
        !           753:                /* XXX 分岐は実行しないといけないのでこのまま進む */
        !           754:                //return;
        !           755:        } else if ((*t).type != T_SPACE) {
        !           756:                error("syntax error: after opword: %s\n", (*t).word.c_str());
        !           757:        }
        !           758:        t++;
        !           759: 
        !           760:        /* 命令語からオペランド種別を取り出す */
        !           761:        optable_t *opt = lookup(op0);
        !           762:        if (opt == NULL) {
        !           763:                error("unknown opcode: %s\n", op0.c_str());
        !           764:        }
        !           765:        switch (opt->oprand_type) {
        !           766:         case OPR_EA:           /* 通常命令用の EA */
        !           767:                parse_arg_ea(list, t);
        !           768:                break;
        !           769:         case OPR_LIST:         /* カンマ区切りリスト */
        !           770:                parse_arg_list(list, t);
        !           771:                break;
        !           772:         case OPR_LITERAL:      /* 書式なし1つの引数 */
        !           773:                parse_arg_literal(list, t);
        !           774:                break;
        !           775:         default:
        !           776:                error("unknown oprand_type=%d (op=%s)\n",
        !           777:                        opt->oprand_type, op0.c_str());
        !           778:                break;
        !           779:        }
        !           780:        DPRINTF(D_PARSE, "oprand.size=%d", oprand.size());
        !           781:        for (int i = 0; i < oprand.size(); i++) {
        !           782:                DPRINTN(D_PARSE, " '%s'", oprand[i].c_str());
        !           783:        }
        !           784:        DPRINTN(D_PARSE, "\n");
        !           785: 
        !           786:        /* 命令語によって分岐 */
        !           787:        opt->func(opt->opword);
        !           788: }
        !           789: 
        !           790: /* オペランドを書式なしとしてパース。全部結合するだけ */
        !           791: void
        !           792: parse_arg_literal(ArrayToken& list, ArrayToken::iterator& t)
        !           793: {
        !           794:        String arg;
        !           795: 
        !           796:        DPRINTF(D_PARSE, "parse_arg_literal\n");
        !           797: 
        !           798:        for (; t != list.end(); t++) {
        !           799:                if ((*t).type == T_END) {
        !           800:                        break;
        !           801:                }
        !           802:                arg += (*t).word;
        !           803:        }
        !           804:        oprand.push_back(arg);
        !           805: }
        !           806: 
        !           807: /* 疑似命令用のオペランド(カンマ区切りリスト)をパース */
        !           808: void
        !           809: parse_arg_list(ArrayToken& list, ArrayToken::iterator& t)
        !           810: {
        !           811:        String arg;
        !           812: 
        !           813:        DPRINTF(D_PARSE, "parse_arg_list\n");
        !           814: 
        !           815:        for (; t != list.end(); t++) {
        !           816:                if ((*t).type == T_COMMA || (*t).type == T_END) {
        !           817:                        oprand.push_back(arg);
        !           818:                        arg.clear();
        !           819:                } else if ((*t).type != T_SPACE) {
        !           820:                        arg += (*t).word;
        !           821:                }
        !           822:        }
        !           823: }
        !           824: 
        !           825: /* 命令のオペランド (EA) をパース */
        !           826: void
        !           827: parse_arg_ea(ArrayToken& list, ArrayToken::iterator& t)
        !           828: {
        !           829:        DPRINTF(D_PARSE, "parse_arg_ea\n");
        !           830: #if 1
        !           831:        /* XXX オペランドはとりあえず旧パーサの動作をシミュレートしておく */
        !           832:        String arg;
        !           833:        for (; t != list.end(); t++) {
        !           834:                if ((*t).type == T_COMMA || (*t).type == T_END) {
        !           835:                        oprand.push_back(arg);
        !           836:                        arg.clear();
        !           837:                } else if ((*t).type != T_SPACE) {
        !           838:                        arg += (*t).word;
        !           839:                }
        !           840:        }
        !           841: #endif
        !           842: }
        !           843: 
        !           844: /* IOCS コールマクロを定義 */
        !           845: void
        !           846: include_iocs()
        !           847: {
        !           848:        std::pair<LabelHash::iterator, bool> r;
        !           849: 
        !           850:        for (int i = 0; i < countof(iocscall); i++) {
        !           851:                String name(iocscall[i]);
        !           852:                if (name.size() == 0 || name[0] == '$') {
        !           853:                        continue;
        !           854:                }
        !           855:                String var = num2hex(i);
        !           856: 
        !           857:                r = label_list.insert(std::make_pair(name, var));
        !           858:                if (r.second == 0) {
        !           859:                        error("iocscall macro '%s' is duplicated\n", name.c_str());
        !           860:                }
        !           861:                //DPRINTF(D_LABEL, "LABEL '%s' <= '%s'\n", name.c_str(), var.c_str());
        !           862:        }
        !           863: }
        !           864: 
        !           865: /* ラベルをリストに記憶 */
        !           866: void
        !           867: add_label(String& label)
        !           868: {
        !           869:        std::pair<LabelHash::iterator, bool> r;
        !           870:        String addr;
        !           871: 
        !           872:        addr = num2hex(::pc);
        !           873:        r = label_list.insert(std::make_pair(label, addr));
        !           874:        if (r.second == 0) {
        !           875:                error("label '%s' is duplicated\n", label.c_str());
        !           876:        }
        !           877:        DPRINTF(D_LABEL, "LABEL '%s' <= '%s'\n", label.c_str(), addr.c_str());
        !           878: }
        !           879: 
        !           880: /*
        !           881:  * リストからラベルを探索。
        !           882:  * 見付かれば var に置換後の文字列を格納して true を返す。
        !           883:  * 見付からなければ false を返す。
        !           884:  */
        !           885: bool
        !           886: find_label(String& label, String& var)
        !           887: {
        !           888:        LabelHash::iterator i;
        !           889: 
        !           890:        i = label_list.find(label);
        !           891:        if (i == label_list.end()) {
        !           892:                DPRINTF(D_LABEL, "'%s' => NOT FOUND\n", label.c_str());
        !           893:                return false;
        !           894:        }
        !           895:        var = (*i).second;
        !           896:        DPRINTF(D_LABEL, "'%s' => '%s'\n", label.c_str(), var.c_str());
        !           897:        return true;
        !           898: }
        !           899: 
        !           900: /* 命令をテーブルから検索 */
        !           901: optable_t *
        !           902: lookup(String& op)
        !           903: {
        !           904:        optable_t *t;
        !           905: 
        !           906:        for (t = optable; t->opname; t++) {
        !           907:                if (strcasecmp(op.c_str(), t->opname) == 0) {
        !           908:                        return t;
        !           909:                }
        !           910:        }
        !           911:        return NULL;
        !           912: }
        !           913: 
        !           914: /* .cinclude 擬似命令 */
        !           915: void
        !           916: op_cinclude(uint16_t opword)
        !           917: {
        !           918:        if (format == FORMAT_C) {
        !           919:                fprintf(outfp, "#include %s\n", oprand[0].c_str());
        !           920:        }
        !           921: }
        !           922: 
        !           923: /* .org 擬似命令 */
        !           924: void
        !           925: op_org(uint16_t opword)
        !           926: {
        !           927:        if (oprand.size() != 1) {
        !           928:                error(".org must have 1 oprand\n");
        !           929:        }
        !           930:        origin = tonumber(oprand[0]);
        !           931:        pc = origin;
        !           932:        DPRINTF(D_INOUT, "set origin=%06X\n", origin);
        !           933: }
        !           934: 
        !           935: /* .start 擬似命令 */
        !           936: void
        !           937: op_start(uint16_t opword)
        !           938: {
        !           939:        /* C出力なら引数が必要。書式が変か… */
        !           940:        if (format == FORMAT_C) {
        !           941:                if (oprand.size() < 1) {
        !           942:                        error(".start needs 1 oprand for C output\n");
        !           943:                }
        !           944:                current_name = oprand[0];
        !           945:        }
        !           946: 
        !           947:        outbin.erase();
        !           948:        rept_start = -1;
        !           949:        rept_count = 0;
        !           950: }
        !           951: 
        !           952: /* .end 擬似命令 */
        !           953: void
        !           954: op_end(uint16_t opword)
        !           955: {
        !           956:        /* 出力は必ずワード単位にする */
        !           957:        op_even(0);
        !           958: 
        !           959:        /* 2nd ステージ (ラベルの解決) */
        !           960:        DPRINTN(D_STAGE, "\n2nd stage\n");
        !           961:        for (ArrayRef::iterator i = ref_list.begin(); i != ref_list.end(); ) {
        !           962:                uint32_t uval;
        !           963:                int val;
        !           964: 
        !           965:                /* 構造体を取り出す */
        !           966:                REF *ref = *i;
        !           967:                DPRINTN_ref(D_INOUT, ref);
        !           968: 
        !           969:                line = ref->line;
        !           970: 
        !           971:                /* 値を計算。ラベルが解決できなければ向こうでエラーにする */
        !           972:                calc_expr(ref->expr, uval, true);
        !           973:                val = uval;
        !           974: 
        !           975:                /* 種別ごとに範囲チェックして出力 */
        !           976: DPRINTF(D_INOUT, "val=%d\n", val);
        !           977:                switch (ref->type) {
        !           978:                 case REFTYPE_BYTE:
        !           979:                        if (val > 127 || val < -128) {
        !           980:                                ::line = ref->line;
        !           981:                                error("%d is insufficient in byte data\n", val);
        !           982:                        }
        !           983:                        DPRINTF(D_INOUT, "pos=%d => $%02x\n", ref->pos, val & 0xff);
        !           984:                        outbin[ref->pos] = val;
        !           985:                        break;
        !           986: 
        !           987:                 case REFTYPE_WORD:
        !           988:                        if (val > 32767 || val < -32768) {
        !           989:                                ::line = ref->line;
        !           990:                                error("%d is insufficient in word data\n\n", val);
        !           991:                        }
        !           992:                        DPRINTF(D_INOUT, "pos=%d => $%04x\n", ref->pos, val & 0xffff);
        !           993:                        outbin[ref->pos    ] = (val >> 8);
        !           994:                        outbin[ref->pos + 1] = (val & 0xff);
        !           995:                        break;
        !           996: 
        !           997:                 case REFTYPE_LONG:
        !           998:                        DPRINTF(D_INOUT, "pos=%d => $%08x\n", ref->pos, val);
        !           999:                        outbin[ref->pos    ] = (val >> 24) & 0xff;
        !          1000:                        outbin[ref->pos + 1] = (val >> 16) & 0xff;
        !          1001:                        outbin[ref->pos + 2] = (val >> 8)  & 0xff;
        !          1002:                        outbin[ref->pos + 3] =  val & 0xff;
        !          1003:                        break;
        !          1004: 
        !          1005:                 default:
        !          1006:                        error("unsupported reftype: %d\n", (int)ref->type);
        !          1007:                        break;
        !          1008:                }
        !          1009: 
        !          1010:                /* 解決したので削除 */
        !          1011:                ref_list.erase(i);
        !          1012:                delete ref;
        !          1013:        }
        !          1014: 
        !          1015:        /* 3rd ステージというか出力 */
        !          1016:        DPRINTN(D_STAGE, "\n3rd stage\n");
        !          1017:        switch (format) {
        !          1018:         case FORMAT_C:
        !          1019:                format_c();
        !          1020:                break;
        !          1021:         case FORMAT_BINARY:
        !          1022:                format_binary();
        !          1023:                break;
        !          1024:        }
        !          1025: 
        !          1026:        DPRINTN(D_STAGE, "\n3rd stage end\n\n");
        !          1027: }
        !          1028: 
        !          1029: /* Cソース形式で出力 */
        !          1030: void
        !          1031: format_c()
        !          1032: {
        !          1033:        fprintf(outfp, "\n");
        !          1034:        fprintf(outfp, "const BYTE %s[] = {", current_name.c_str());
        !          1035:        for (int i = 0; i < outbin.size(); i++) {
        !          1036:                if ((i % 8) == 0) {
        !          1037:                        fprintf(outfp, "\n\t");
        !          1038:                }
        !          1039:                fprintf(outfp, "0x%02x,", (uint8_t)outbin[i]);
        !          1040:        }
        !          1041:        fprintf(outfp, "\n};\n");
        !          1042:        fprintf(outfp, "const int %s_size = %d;\n",
        !          1043:                current_name.c_str(), (int)outbin.size());
        !          1044: }
        !          1045: 
        !          1046: /* バイナリ形式で出力 */
        !          1047: void
        !          1048: format_binary()
        !          1049: {
        !          1050:        String buf;
        !          1051:        int n;
        !          1052: 
        !          1053:        n = 0;
        !          1054:        for (;;) {
        !          1055:                buf = outbin.substr(n, 4096);
        !          1056:                if (buf.size() == 0) {
        !          1057:                        break;
        !          1058:                }
        !          1059: 
        !          1060:                fwrite(buf.c_str(), 1, buf.size(), outfp);
        !          1061:                n += buf.size();
        !          1062:        }
        !          1063: }
        !          1064: 
        !          1065: /* .dc 擬似命令 */
        !          1066: void
        !          1067: op_dc(uint16_t opword)
        !          1068: {
        !          1069:        ArrayString::iterator i;
        !          1070:        for (i = oprand.begin(); i != oprand.end(); i++) {
        !          1071:                String arg = *i;
        !          1072: 
        !          1073:                /* .b でダブルクォートから始まってたら文字列 */
        !          1074:                if (size_sfx == 1 && arg[0] == '\x22') {
        !          1075:                        /* 文字列を解析 */
        !          1076:                        String str = parse_string(arg);
        !          1077: 
        !          1078:                        /* 日本語文字コードを変換 */
        !          1079:                        str = convert_charset(str);
        !          1080: 
        !          1081:                        for (int j = 0; j < str.size(); j++) {
        !          1082:                                output_b(str[j]);
        !          1083:                        }
        !          1084: 
        !          1085:                } else if (size_sfx == 1 && arg[0] == '\'') {
        !          1086:                        /* XXX まだこれには対応できないので旧方式で対応 */
        !          1087:                        output_b(tonumber(arg));
        !          1088: 
        !          1089:                } else {
        !          1090:                        /* そうでなければ式として評価 */
        !          1091:                        ArrayString expr;
        !          1092:                        uint32_t val;
        !          1093:                        parse_expr(*i, expr);
        !          1094:                        if (calc_expr(expr, val, false)) {
        !          1095:                                /* 解決できたので出力 */
        !          1096:                                output_bin(val, size_sfx);
        !          1097:                        } else {
        !          1098:                                /* 解決できなかった */
        !          1099:                                switch (size_sfx) {
        !          1100:                                 case 1:
        !          1101:                                        add_expr(::outbin.size(), REFTYPE_BYTE, expr);
        !          1102:                                        break;
        !          1103:                                 case 2:
        !          1104:                                        add_expr(::outbin.size(), REFTYPE_WORD, expr);
        !          1105:                                        break;
        !          1106:                                 case 4:
        !          1107:                                        add_expr(::outbin.size(), REFTYPE_LONG, expr);
        !          1108:                                        break;
        !          1109:                                 default:
        !          1110:                                        abort();
        !          1111:                                }
        !          1112:                                output_bin(0, size_sfx);
        !          1113:                        }
        !          1114:                }
        !          1115:        }
        !          1116: }
        !          1117: 
        !          1118: /* .ds 擬似命令 */
        !          1119: void
        !          1120: op_ds(uint16_t opword)
        !          1121: {
        !          1122:        ArrayString::iterator i;
        !          1123:        for (i = oprand.begin(); i != oprand.end(); i++) {
        !          1124:                int size = tonumber(*i);
        !          1125:                output_ds(size * size_sfx);
        !          1126:        }
        !          1127: }
        !          1128: 
        !          1129: /* .even 擬似命令 */
        !          1130: void
        !          1131: op_even(uint16_t opword)
        !          1132: {
        !          1133:        /* 奇数なら偶数に合わせる */
        !          1134:        if ((outbin.size() & 1)) {
        !          1135:                output_b(0);
        !          1136:        }
        !          1137: }
        !          1138: 
        !          1139: /* .equ 擬似命令 */
        !          1140: void
        !          1141: op_equ(uint16_t opword)
        !          1142: {
        !          1143:        if (label0.empty()) {
        !          1144:                error(".equ must have a label\n");
        !          1145:        }
        !          1146:        if (oprand.size() != 1) {
        !          1147:                error(".equ must have 1 oprand\n");
        !          1148:        }
        !          1149: 
        !          1150:        /* ラベルの値を PC ではなくオペランド指定の値に差し替える */
        !          1151:        LabelHash::iterator i;
        !          1152:        /* 見付からないはずはないのでエラー処理省略? */
        !          1153:        i = label_list.find(label0);
        !          1154:        (*i).second = oprand[0];
        !          1155:        DPRINTF(D_LABEL, "LABEL '%s' EQU '%s'\n",
        !          1156:                (*i).first.c_str(), (*i).second.c_str());
        !          1157: }
        !          1158: 
        !          1159: /* .rept 擬似命令 */
        !          1160: void
        !          1161: op_rept(uint16_t opword)
        !          1162: {
        !          1163:        ArrayString expr;
        !          1164:        uint32_t cnt;
        !          1165: 
        !          1166:        if (rept_start != -1) {
        !          1167:                error(".rept duplicated\n");
        !          1168:        }
        !          1169: 
        !          1170:        /* ここを記憶しておくだけ */
        !          1171:        rept_start = outbin.size();
        !          1172:        /* 回数は <式> で、この時点で解決できなければいけない */
        !          1173:        parse_expr(oprand[0], expr);
        !          1174:        calc_expr(expr, cnt, true);
        !          1175:        rept_count = cnt;
        !          1176: 
        !          1177:        DPRINTF(D_INOUT, ".rept start=$%x count=$%x\n",
        !          1178:                rept_start, rept_count);
        !          1179: }
        !          1180: 
        !          1181: /* .endrept 擬似命令 */
        !          1182: /* XXX 最終的には HAS に合わせて endm にしたい */
        !          1183: void
        !          1184: op_endrept(uint16_t opword)
        !          1185: {
        !          1186:        String target;
        !          1187:        int rept_size;
        !          1188:        int total_size;
        !          1189: 
        !          1190:        if (rept_start == -1) {
        !          1191:                error(".endrept without .rept\n");
        !          1192:        }
        !          1193: 
        !          1194:        /* .rept の位置からここまでの内容を取得 */
        !          1195:        rept_size = outbin.size() - rept_start;
        !          1196:        target = outbin.substr(rept_start, rept_size);
        !          1197: 
        !          1198:        /* それを (rept_count-1) 回出力。1回目はすでに出力してあるから */
        !          1199:        rept_count--;
        !          1200:        for (int i = 0; i < rept_count; i++) {
        !          1201:                outbin += target;
        !          1202:        }
        !          1203: 
        !          1204:        total_size = rept_size * rept_count;
        !          1205:        pc += total_size;
        !          1206:        DPRINTF(D_INOUT, "output $%x(%d) bytes x $%x(%d) = $%x(%d) bytes\n",
        !          1207:                rept_size, rept_size,
        !          1208:                rept_count, rept_count,
        !          1209:                total_size, total_size);
        !          1210: 
        !          1211:        /* パラメータをクリア */
        !          1212:        rept_count = 0;
        !          1213:        rept_start = -1;
        !          1214: }
        !          1215: 
        !          1216: /* IOCS マクロ命令 */
        !          1217: void
        !          1218: op_iocs(uint16_t opword)
        !          1219: {
        !          1220:        char moveqbuf[32];
        !          1221:        int num;
        !          1222: 
        !          1223:        num = tonumber(oprand[0]) & 0xff;
        !          1224:        snprintf(moveqbuf, sizeof(moveqbuf), " moveq.l #$%x,d0", num);
        !          1225:        String moveq(moveqbuf);
        !          1226:        String trap(" trap #15");
        !          1227: 
        !          1228:        parse_asm(moveq);
        !          1229:        parse_asm(trap);
        !          1230: }
        !          1231: 
        !          1232: /* bcc */
        !          1233: /* XXX Bcc.b <cond>,<label> というニーモニックにする */
        !          1234: void
        !          1235: op_bcc(uint16_t opword)
        !          1236: {
        !          1237:        int cc;
        !          1238: 
        !          1239:        /* bra/bcc だけ .s を .b に読み替えて認める */
        !          1240:        if (size_sfx == 0 && tolower(size0[1]) == 's') {
        !          1241:                size_sfx = 1;
        !          1242:        }
        !          1243: 
        !          1244:        if (size_sfx == 1) {
        !          1245:                cc = get_cc(oprand[0]);
        !          1246:                add_ref(REFTYPE_BYTE, oprand[1]);
        !          1247: 
        !          1248:                opword |= cc << 8;
        !          1249:                output_w(opword);
        !          1250:        } else {
        !          1251:                error("unsupported size: %s%s\n", op0.c_str(), size0.c_str());
        !          1252:        }
        !          1253: }
        !          1254: 
        !          1255: /* bra */
        !          1256: void
        !          1257: op_bra(uint16_t opword)
        !          1258: {
        !          1259:        /* bra/bcc だけ .s を .b に読み替えて認める */
        !          1260:        if (size_sfx == 0 && tolower(size0[1]) == 's') {
        !          1261:                size_sfx = 1;
        !          1262:        }
        !          1263: 
        !          1264:        if (size_sfx == 1) {
        !          1265:                add_ref(REFTYPE_BYTE, oprand[0]);
        !          1266:                output_w(opword);
        !          1267:        } else {
        !          1268:                error("unsupported size: %s%s\n", op0.c_str(), size0.c_str());
        !          1269:        }
        !          1270: }
        !          1271: 
        !          1272: /* clr */
        !          1273: void
        !          1274: op_clr(uint16_t opword)
        !          1275: {
        !          1276:        EA dst;
        !          1277: 
        !          1278:        dst = get_ea(oprand[0]);
        !          1279: 
        !          1280:        opword |= dst.mode | size6[size_sfx];
        !          1281: 
        !          1282:        output_w(opword);
        !          1283:        output_ea(dst);
        !          1284: }
        !          1285: 
        !          1286: /* dbra */
        !          1287: void
        !          1288: op_dbra(uint16_t opword)
        !          1289: {
        !          1290:        EA src;
        !          1291: 
        !          1292:        src = get_ea(oprand[0]);
        !          1293:        add_ref(REFTYPE_WORD, oprand[1]);
        !          1294: 
        !          1295:        opword |= src.num();
        !          1296: 
        !          1297:        output_w(opword);
        !          1298:        output_w(0);
        !          1299: }
        !          1300: 
        !          1301: /* jmp */
        !          1302: void
        !          1303: op_jmp(uint16_t opword)
        !          1304: {
        !          1305:        EA dst;
        !          1306: 
        !          1307:        dst = get_ea(oprand[0]);
        !          1308: 
        !          1309:        output_w(opword | dst.mode);
        !          1310:        output_ea(dst);
        !          1311: }
        !          1312: 
        !          1313: /* lea.l */
        !          1314: void
        !          1315: op_lea(uint16_t opword)
        !          1316: {
        !          1317:        EA src, dst;
        !          1318: 
        !          1319:        if (size_sfx == -1) {
        !          1320:                size_sfx = 4;
        !          1321:        }
        !          1322:        if (size_sfx != 4) {
        !          1323:                error("invalid opcode: %s%s\n", op0.c_str(), size0.c_str());
        !          1324:        }
        !          1325: 
        !          1326:        src = get_ea(oprand[0]);
        !          1327:        dst = get_ea(oprand[1]);
        !          1328: 
        !          1329:        if (dst.type() != 0x01) {
        !          1330:                error("syntax error: LEA dst must be An\n");
        !          1331:        }
        !          1332: 
        !          1333:        opword |= src.mode;
        !          1334:        opword |= dst.num() << 9;
        !          1335: 
        !          1336:        output_w(opword);
        !          1337:        output_ea(src);
        !          1338: }
        !          1339: 
        !          1340: /* move */
        !          1341: void
        !          1342: op_move(uint16_t opword)
        !          1343: {
        !          1344:        EA src, dst;
        !          1345: 
        !          1346:        /* move an,usp */
        !          1347:        if (oprand[1] == "usp") {
        !          1348:                if (size_sfx == -1) {
        !          1349:                        size_sfx = 4;
        !          1350:                }
        !          1351:                if (size_sfx != 4) {
        !          1352:                        error("syntax error: MOVE An,USP must .L");
        !          1353:                }
        !          1354:                src = get_ea(oprand[0], EAT_An);
        !          1355:                opword = 0x4e60 + src.num();
        !          1356:                output_w(opword);
        !          1357:                return;
        !          1358:        }
        !          1359:        /* move usp,an */
        !          1360:        if (oprand[0] == "usp") {
        !          1361:                dst = get_ea(oprand[1]);
        !          1362:                if (size_sfx == -1) {
        !          1363:                        size_sfx = 4;
        !          1364:                }
        !          1365:                if (size_sfx != 4) {
        !          1366:                        error("syntax error: MOVE USP,An must .L");
        !          1367:                }
        !          1368:                opword = 0x4e68 + dst.num();
        !          1369:                output_w(opword);
        !          1370:                return;
        !          1371:        }
        !          1372: 
        !          1373:        src = get_ea(oprand[0]);
        !          1374:        dst = get_ea(oprand[1]);
        !          1375: 
        !          1376:        switch (size_sfx) {
        !          1377:         case 1:        opword = 0x1000;        src.size = 1;   break;
        !          1378:         case 2:        opword = 0x3000;        src.size = 2;   break;
        !          1379:         case 4:        opword = 0x2000;        src.size = 4;   break;
        !          1380:        }
        !          1381:        opword |= src.mode;
        !          1382:        opword |= (dst.type() | (dst.num() << 3)) << 6;
        !          1383: 
        !          1384:        output_w(opword);
        !          1385:        output_ea(src);
        !          1386:        output_ea(dst);
        !          1387: }
        !          1388: 
        !          1389: /* movem.l */
        !          1390: void
        !          1391: op_movem(uint16_t opword)
        !          1392: {
        !          1393:        uint16_t list;
        !          1394:        EA ea;
        !          1395:        String errmsg;
        !          1396: 
        !          1397:        if (size_sfx == 4) {    /* .L */
        !          1398:                opword |= 0x0040;
        !          1399:        }
        !          1400: 
        !          1401:        if (get_reglist(oprand[0], list)
        !          1402:         && try_ea(oprand[1], ea, errmsg, EAT_AI | EAT_APD | EAT_AREL | EAT_ABS))
        !          1403:        {
        !          1404:                /* movem.l list,ea */
        !          1405:                opword |= ea.mode;
        !          1406: 
        !          1407:                /* -(An) の時だけビット並び順を反転 */
        !          1408:                if ((ea.mode & 0x38) == EA_An_PD) {
        !          1409:                        uint16_t rev = 0;
        !          1410:                        for (int i = 0; i < 16; i++) {
        !          1411:                                if ((list & (1 << i)) != 0) {
        !          1412:                                        rev |= 0x8000 >> i;
        !          1413:                                }
        !          1414:                        }
        !          1415:                        list = rev;
        !          1416:                }
        !          1417: 
        !          1418:                output_w(opword);
        !          1419:                output_w(list);
        !          1420:                output_ea(ea);
        !          1421:                return;
        !          1422:        }
        !          1423:        if (try_ea(oprand[0], ea, errmsg, EAT_AI | EAT_API | EAT_AREL | EAT_ABS)
        !          1424:         && get_reglist(oprand[1], list))
        !          1425:        {
        !          1426:                /* movem.l ea,list */
        !          1427:                opword |= ea.mode;
        !          1428:                opword |= 0x0400;       /* ea->list */
        !          1429: 
        !          1430:                output_w(opword);
        !          1431:                output_w(list);
        !          1432:                output_ea(ea);
        !          1433:                return;
        !          1434:        }
        !          1435: 
        !          1436:        error("invalid movem oprand\n");
        !          1437: }
        !          1438: 
        !          1439: /* moveq.l */
        !          1440: void
        !          1441: op_moveq(uint16_t opword)
        !          1442: {
        !          1443:        EA src, dst;
        !          1444: 
        !          1445:        if (size_sfx == -1) {
        !          1446:                size_sfx = 4;
        !          1447:        }
        !          1448:        if (size_sfx != 4) {
        !          1449:                error("invalid opcode: %s%s\n", op0.c_str(), size0.c_str());
        !          1450:        }
        !          1451: 
        !          1452:        src = get_ea(oprand[0]);
        !          1453:        dst = get_ea(oprand[1]);
        !          1454:        if (src.mode != EA_IMMEDIATE) {
        !          1455:                error("invalid oprand\n");
        !          1456:        }
        !          1457:        if (src.val > 0xff) {
        !          1458:                error("moveq.l #$%x too large\n", src.val);
        !          1459:        }
        !          1460: 
        !          1461:        opword |= src.val & 0xff;
        !          1462:        opword |= dst.num() << 9;
        !          1463: 
        !          1464:        output_w(opword);
        !          1465: }
        !          1466: 
        !          1467: /* sub */
        !          1468: void
        !          1469: op_sub(uint16_t opword)
        !          1470: {
        !          1471:        EA src = get_ea(oprand[0]);
        !          1472:        EA dst = get_ea(oprand[1]);
        !          1473: 
        !          1474:        switch (size_sfx) {
        !          1475:         case 1:        opword |= 0x00; break;
        !          1476:         case 2:        opword |= 0x40; break;
        !          1477:         case 4:        opword |= 0x80; break;
        !          1478:         default:
        !          1479:                error("syntax error: size?");
        !          1480:        }
        !          1481: 
        !          1482:        if (dst.type() == 0) {
        !          1483:                // SUB.S <ea>,Dn
        !          1484:                // XXX src の正当性チェック
        !          1485:                opword |= src.mode;
        !          1486:                opword |= dst.num() << 9;
        !          1487:                output_w(opword);
        !          1488:                output_ea(src);
        !          1489:                return;
        !          1490:        }
        !          1491:        if (dst.type() == 0) {
        !          1492:                // SUB.S Dn,<ea>
        !          1493:                // XXX dst の正当性チェック
        !          1494:                opword |= 0x0100;
        !          1495:                opword |= src.num() << 9;
        !          1496:                opword |= dst.mode;
        !          1497:                output_w(opword);
        !          1498:                output_ea(dst);
        !          1499:                return;
        !          1500:        }
        !          1501:        error("syntax error");
        !          1502: }
        !          1503: 
        !          1504: /* suba */
        !          1505: void
        !          1506: op_suba(uint16_t opword)
        !          1507: {
        !          1508:        EA src = get_ea(oprand[0]);
        !          1509:        EA dst = get_ea(oprand[1]);
        !          1510:        switch (size_sfx) {
        !          1511:         case -1:
        !          1512:         case 2:        opword |= 0x0000;       break;
        !          1513:         case 4:        opword |= 0x0100;       break;
        !          1514:         default:
        !          1515:                error("syntax error: .B is invalid\n");
        !          1516:        }
        !          1517:        opword |= src.mode;
        !          1518:        opword |= dst.num() << 9;
        !          1519:        output_w(opword);
        !          1520:        output_ea(src);
        !          1521: }
        !          1522: 
        !          1523: /* trap */
        !          1524: void
        !          1525: op_trap(uint16_t opword)
        !          1526: {
        !          1527:        EA src;
        !          1528: 
        !          1529:        src = get_ea(oprand[0]);
        !          1530:        if (src.mode != EA_IMMEDIATE) {
        !          1531:                error("invalid oprand\n");
        !          1532:        }
        !          1533:        if (src.val > 15) {
        !          1534:                error("trap #$%x too large\n", src.val);
        !          1535:        }
        !          1536: 
        !          1537:        opword |= src.val;
        !          1538:        output_w(opword);
        !          1539: }
        !          1540: 
        !          1541: /* nop、rts などオペランドを持たないやつ */
        !          1542: void
        !          1543: op_noarg(uint16_t opword)
        !          1544: {
        !          1545:        output_w(opword);
        !          1546: }
        !          1547: 
        !          1548: /*
        !          1549:  * 指定されたeatype に bit が立ってなければ、
        !          1550:  * この命令でこの EA は認められていない。
        !          1551:  */
        !          1552: #define check_eatype(bit)      \
        !          1553:        if ((eatype & (bit)) == 0) {    \
        !          1554:                DPRINTF(D_EA, "EAT 0x%x not match in eatype=0x%x\n", bit, eatype);      \
        !          1555:                errmsg = "invalid ea";  \
        !          1556:                return false;   \
        !          1557:        }
        !          1558: 
        !          1559: /*
        !          1560:  * EA がパースできるかどうかを返す。
        !          1561:  * errmes が NULL でなければ、パースできなかった時のエラーメッセージを
        !          1562:  * 格納する。
        !          1563:  */
        !          1564: bool
        !          1565: try_ea(String& eabuf, EA& ea, String& errmsg, int eatype)
        !          1566: {
        !          1567: #if defined(_MSC_VER)
        !          1568:        char buf[BUFSIZE];
        !          1569: #else
        !          1570:        char buf[eabuf.size() + 1];
        !          1571: #endif
        !          1572:        int i;
        !          1573: 
        !          1574: #if defined(_MSC_VER)
        !          1575:        strncpy(buf, eabuf.c_str(), sizeof(buf) - 1);
        !          1576:        buf[sizeof(buf) - 1] = '\0';
        !          1577: #else
        !          1578:        strcpy(buf, eabuf.c_str());
        !          1579: #endif
        !          1580: 
        !          1581:        /* 固定文字列との比較。見つかればすぐ帰れる */
        !          1582:        for (i = 0; i < countof(regname); i++) {
        !          1583:                if (strcasecmp(buf, regname[i]) == 0) {
        !          1584:                        ea.mode = i;
        !          1585:                        DPRINTF(D_EA, "ea=reg,%s -> 0x%x\n", regname[ea.mode], ea.mode);
        !          1586:                        check_eatype(1 << (i / 8));
        !          1587:                        return true;
        !          1588:                }
        !          1589:        }
        !          1590: 
        !          1591:        /* d16(pc) */
        !          1592:        i = strlen(buf) - 4;
        !          1593:        if (i > 0 && strcasecmp(buf + i, "(pc)") == 0) {
        !          1594:                String label = eabuf.substr(0, i);
        !          1595:                add_ref(REFTYPE_WORD, label);
        !          1596:                ea.mode = EA_d16PC;
        !          1597:                DPRINTF(D_EA, "ea=d16(PC) label=%s\n", label.c_str());
        !          1598:                check_eatype(EAT_PCREL);
        !          1599:                return true;
        !          1600:        }
        !          1601: 
        !          1602:        /* #imm */
        !          1603:        /* XXX マクロ展開後が #imm だったら解決できないこれ */
        !          1604:        if (buf[0] == '#') {
        !          1605:                String label = eabuf.substr(1);
        !          1606:                ea.mode = EA_IMMEDIATE;
        !          1607:                ea.val = tonumber(label);
        !          1608:                DPRINTF(D_EA, "ea=#imm,$%x\n", ea.val);
        !          1609:                check_eatype(EAT_IMM);
        !          1610:                return true;
        !          1611:        }
        !          1612: 
        !          1613:        /* XXX An間接、PC間接系は未実装 */
        !          1614: 
        !          1615:        /* どれでもなさそうなら? */
        !          1616:        /* Abs[.WL] */
        !          1617:        ea.size = 0;
        !          1618:        i = strlen(buf) - 2;
        !          1619:        if (i > 0) {
        !          1620:                if (strcasecmp(buf + i, ".W") == 0) {
        !          1621:                        ea.size = 2;
        !          1622:                } else if (strcasecmp(buf + i, ".L") == 0) {
        !          1623:                        ea.size = 4;
        !          1624:                }
        !          1625:        }
        !          1626:        ea.mode = EA_ABS_W;
        !          1627:        int intval;
        !          1628:        if (parse_number(eabuf, &intval)) {
        !          1629:                ea.val = intval;
        !          1630:                if (ea.size == 0) {
        !          1631:                        ea.size = (ea.val > 0xffff) ? 4 : 2;
        !          1632:                }
        !          1633:                ea.mode = (ea.size == 4) ? EA_ABS_L : EA_ABS_W;
        !          1634:                if (ea.val > 0xffff && ea.mode == EA_ABS_W) {
        !          1635:                        errmsg = "Exceed Abs.W";
        !          1636:                        return false;
        !          1637:                }
        !          1638:                DPRINTF(D_EA, "ea=ABS.%c,$%x\n",
        !          1639:                        (ea.mode==EA_ABS_W)?'W':'L', ea.val);
        !          1640:                check_eatype(EAT_ABS);
        !          1641:                return true;
        !          1642:        }
        !          1643: 
        !          1644:        DPRINTF(D_EA, "unknown EA: %s\n", buf);
        !          1645:        errmsg = "unknown EA: ";
        !          1646:        errmsg += eabuf;
        !          1647:        return false;
        !          1648: }
        !          1649: 
        !          1650: /*
        !          1651:  * EA をパースして返す。
        !          1652:  * 成功すれば EA を返す。失敗すればエラー終了する。
        !          1653:  */
        !          1654: EA
        !          1655: get_ea(String& eabuf)
        !          1656: {
        !          1657:        return get_ea(eabuf, EAT_ALL);
        !          1658: }
        !          1659: 
        !          1660: /*
        !          1661:  * EA をパースして返す。
        !          1662:  * eatype は許可する EA タイプ。
        !          1663:  * 成功すれば EA を返す。失敗すればエラー終了する。
        !          1664:  */
        !          1665: EA
        !          1666: get_ea(String& eabuf, int eatype)
        !          1667: {
        !          1668:        EA ea;
        !          1669:        String errmsg;
        !          1670: 
        !          1671:        if (try_ea(eabuf, ea, errmsg, eatype) == false) {
        !          1672:                error("%s", errmsg.c_str());
        !          1673:        }
        !          1674:        return ea;
        !          1675: }
        !          1676: 
        !          1677: /*
        !          1678:  * reglist をパースする。
        !          1679:  * reglist でなさそうならエラーを表示せず false を返す。
        !          1680:  * true を返した場合の list は常に b15-b0 の順で A7-A0/D7-D0。
        !          1681:  */
        !          1682: bool
        !          1683: get_reglist(String& inbuf, uint16_t& list)
        !          1684: {
        !          1685: #if defined(_MSC_VER)
        !          1686:        char buf[BUFSIZE];
        !          1687: #else
        !          1688:        char buf[inbuf.size() + 1];
        !          1689: #endif
        !          1690:        char *s;
        !          1691:        int num;
        !          1692:        int prevnum;
        !          1693:        int Aoffset;
        !          1694:        enum {
        !          1695:                INIT,
        !          1696:                REG,
        !          1697:                NUM1,
        !          1698:                NUM2,
        !          1699:        } state;
        !          1700: 
        !          1701: #if defined(_MSC_VER)
        !          1702:        strncpy(buf, inbuf.c_str(), sizeof(buf) - 1);
        !          1703:        buf[sizeof(buf) - 1] = '\0';
        !          1704: #else
        !          1705:        strcpy(buf, inbuf.c_str());
        !          1706: #endif
        !          1707: 
        !          1708:        state = INIT;
        !          1709:        num = -1;
        !          1710:        prevnum = -1;
        !          1711:        Aoffset = 0;
        !          1712:        for (s = buf; *s; s++) {
        !          1713:                char c = (int)*s;
        !          1714:                if (state == INIT) {
        !          1715:                        if (tolower(c) == 'd') {
        !          1716:                                state = REG;
        !          1717:                                Aoffset = 0;
        !          1718:                                continue;
        !          1719:                        }
        !          1720:                        if (tolower(c) == 'a') {
        !          1721:                                state = REG;
        !          1722:                                Aoffset = 8;
        !          1723:                                continue;
        !          1724:                        }
        !          1725:                        return false;
        !          1726:                } else if (state == REG) {
        !          1727:                        if (!isdigit(c)) {
        !          1728:                                return false;
        !          1729:                        }
        !          1730:                        num = c - '0';
        !          1731:                        num += Aoffset;
        !          1732:                        if (prevnum == -1) {
        !          1733:                                // 単独もしくは範囲指定の1つ目のレジスタ指定
        !          1734:                                list |= (1 << num);
        !          1735:                                state = NUM1;
        !          1736:                        } else {                        
        !          1737:                                // 範囲指定の2つ目のレジスタ
        !          1738:                                for (int i = prevnum; i <= num; i++) {
        !          1739:                                        list |= (1 << i);
        !          1740:                                }
        !          1741:                                prevnum = -1;
        !          1742:                                state = NUM2;
        !          1743:                        }
        !          1744:                        continue;
        !          1745:                } else if (state == NUM1) {
        !          1746:                        // 単独もしくは範囲指定の1つ目のレジスタの後
        !          1747:                        if (c == '/') {
        !          1748:                                prevnum = -1;
        !          1749:                                state = INIT;
        !          1750:                                continue;
        !          1751:                        }
        !          1752:                        if (c == '-') {
        !          1753:                                prevnum = num;
        !          1754:                                state = INIT;
        !          1755:                                continue;
        !          1756:                        }
        !          1757:                        return false;
        !          1758:                } else if (state == NUM2) {
        !          1759:                        // 範囲指定の2つ目のレジスタの後に '-' はこない
        !          1760:                        if (c == '/') {
        !          1761:                                state = INIT;
        !          1762:                                continue;
        !          1763:                        }
        !          1764:                        return false;
        !          1765:                }
        !          1766:                return false;
        !          1767:        }
        !          1768: 
        !          1769:        DPRINTF(D_EA, "reglist = %04X\n", list);
        !          1770:        return true;
        !          1771: }
        !          1772: 
        !          1773: /* cc をパースして返す */
        !          1774: int
        !          1775: get_cc(String& ccbuf)
        !          1776: {
        !          1777:        int i;
        !          1778: 
        !          1779:        for (i = 0; i < countof(ccname); i++) {
        !          1780:                if (strcasecmp(ccbuf.c_str(), ccname[i]) == 0) {
        !          1781:                        DPRINTF(D_EA, "cc=%s -> 0x%x\n", ccname[i], i);
        !          1782:                        return i;
        !          1783:                }
        !          1784:        }
        !          1785: 
        !          1786:        error("unknown CC: %s\n", ccbuf.c_str());
        !          1787:        /* NOTREACHED */
        !          1788:        return 0;
        !          1789: }
        !          1790: 
        !          1791: /* 参照をリストに追加。おもに Bcc と d16(PC) 用? */
        !          1792: void
        !          1793: add_ref(reftype_t type, String& label)
        !          1794: {
        !          1795:        /* expr = label - (pc+2) */
        !          1796:        ArrayString expr;
        !          1797:        expr.push_back(label);
        !          1798:        expr.push_back(num2hex(::pc + 2));
        !          1799:        expr.push_back(String("-"));
        !          1800: 
        !          1801:        /* オフセット */
        !          1802:        int offset;
        !          1803:        switch (type) {
        !          1804:         case REFTYPE_BYTE:
        !          1805:                offset = 1;
        !          1806:                break;
        !          1807:         case REFTYPE_WORD:
        !          1808:         case REFTYPE_LONG:
        !          1809:                offset = 2;
        !          1810:                break;
        !          1811:         default:
        !          1812:                error("unknown reftype %d\n", type);
        !          1813:        }
        !          1814: 
        !          1815:        add_expr(::outbin.size() + offset, type, expr);
        !          1816: }
        !          1817: 
        !          1818: /* EA を出力 */
        !          1819: void
        !          1820: output_ea(EA& ea)
        !          1821: {
        !          1822:        switch (ea.mode) {
        !          1823:         case EA_d16PC:
        !          1824:                output_w(0);
        !          1825:                break;
        !          1826:         case EA_ABS_W:
        !          1827:                output_w(ea.val);
        !          1828:                break;
        !          1829:         case EA_ABS_L:
        !          1830:                output_l(ea.val);
        !          1831:                break;
        !          1832:         case EA_IMMEDIATE:
        !          1833:                output_bin(ea.val, ea.size);
        !          1834:                break;
        !          1835:         default:
        !          1836:                /* それ以外は何もしない */
        !          1837:                break;
        !          1838:        }
        !          1839: }
        !          1840: 
        !          1841: /* nバイトを出力 */
        !          1842: void
        !          1843: output_bin(uint32_t data, int size)
        !          1844: {
        !          1845:        switch (size) {
        !          1846:         case 1:
        !          1847:                output_b(data);
        !          1848:                break;
        !          1849:         case 2:
        !          1850:                output_w(data);
        !          1851:                break;
        !          1852:         case 4:
        !          1853:                output_l(data);
        !          1854:                break;
        !          1855:         default:
        !          1856:                error("output_bin: invalid size %d\n", size);
        !          1857:                break;
        !          1858:        }
        !          1859: }
        !          1860: 
        !          1861: /* 1バイトを出力 */
        !          1862: void
        !          1863: output_b(uint32_t data)
        !          1864: {
        !          1865:        data &= 0xff;
        !          1866:        DPRINTF(D_INOUT, "output: $%06X => $%02X\n", pc, data);
        !          1867:        outbin.push_back(data);
        !          1868:        pc += 1;
        !          1869: }
        !          1870: 
        !          1871: /* 1ワードを出力 */
        !          1872: void
        !          1873: output_w(uint32_t data)
        !          1874: {
        !          1875:        data &= 0xffff;
        !          1876:        DPRINTF(D_INOUT, "output: $%06X => $%04X\n", pc, data);
        !          1877:        outbin.push_back(data >> 8);
        !          1878:        outbin.push_back(data & 0xff);
        !          1879:        pc += 2;
        !          1880: }
        !          1881: 
        !          1882: /* 1ロングワードを出力 */
        !          1883: void
        !          1884: output_l(uint32_t data)
        !          1885: {
        !          1886:        DPRINTF(D_INOUT, "output: $%06X => $%08X\n", pc, data);
        !          1887:        outbin.push_back(data >> 24);
        !          1888:        outbin.push_back((data >> 16) & 0xff);
        !          1889:        outbin.push_back((data >>  8) & 0xff);
        !          1890:        outbin.push_back(data & 0xff);
        !          1891:        pc += 4;
        !          1892: }
        !          1893: 
        !          1894: /* .ds 用に指定の長さを 0 で埋める */
        !          1895: void
        !          1896: output_ds(int size)
        !          1897: {
        !          1898:        DPRINTF(D_INOUT, "output: $%X(%d)bytes\n", size, size);
        !          1899:        String ds(size, '\0');
        !          1900:        outbin += ds;
        !          1901:        pc += size;
        !          1902: }
        !          1903: 
        !          1904: /* 数値を String に変換 */
        !          1905: String
        !          1906: num2str(int num)
        !          1907: {
        !          1908:        char buf[16];
        !          1909:        snprintf(buf, sizeof(buf), "%d", num);
        !          1910:        String ret(buf);
        !          1911:        return ret;
        !          1912: }
        !          1913: 
        !          1914: /* 数値を $HHHH 形式の String に変換 */
        !          1915: String
        !          1916: num2hex(int num)
        !          1917: {
        !          1918:        char buf[16];
        !          1919:        snprintf(buf, sizeof(buf), "$%x", num);
        !          1920:        String ret(buf);
        !          1921:        return ret;
        !          1922: }
        !          1923: 
        !          1924: /*
        !          1925:  * 文字列を数値に変換。
        !          1926:  * 変換できれば true、できなければ false を返す。
        !          1927:  * 変換できた場合は、numptr が NULL でなければ結果を格納して返す。
        !          1928:  */
        !          1929: bool
        !          1930: parse_number(String& str, int *numptr)
        !          1931: {
        !          1932:        try {
        !          1933:                /* 先頭が数字なら10進数 */
        !          1934:                if (isdigit((int)str[0])) {
        !          1935:                        throw (int)strtol(str.c_str(), NULL, 10);
        !          1936:                }
        !          1937: 
        !          1938:                /* $HH 形式なら16進数 */
        !          1939:                if (str[0] == '$' && str.size() > 1) {
        !          1940:                        String buf = str;
        !          1941:                        buf.erase(0, 1);
        !          1942:                        /* エラー処理無視 */
        !          1943:                        throw (int)strtol(buf.c_str(), NULL, 16);
        !          1944:                }
        !          1945: 
        !          1946:                /* 'X'形式なら1文字 */
        !          1947:                if (str[0] == '\'' && str.size() == 3 && str[2] == '\'') {
        !          1948:                        throw (int)str[1];
        !          1949:                }
        !          1950: 
        !          1951:                /* (既出の)ラベルと一致するか */
        !          1952:                String val;
        !          1953:                if (find_label(str, val)) {
        !          1954:                        int num;
        !          1955:                        if (parse_number(val, &num)) {
        !          1956:                                throw num;
        !          1957:                        }
        !          1958:                }
        !          1959:        } catch (int num) {
        !          1960:                /* 見つかった時に例外でここに飛んでくる */
        !          1961:                if (numptr) {
        !          1962:                        *numptr = num;
        !          1963:                }
        !          1964:                return true;
        !          1965:        }
        !          1966: 
        !          1967:        /* 解決できなかった */
        !          1968:        return false;
        !          1969: }
        !          1970: 
        !          1971: /* 文字列を数値に変換。変換できなければアセンブルエラーで停止する */
        !          1972: int
        !          1973: tonumber(String& str)
        !          1974: {
        !          1975:        int num;
        !          1976: 
        !          1977:        if (!parse_number(str, &num)) {
        !          1978:                error("invalid number: %s\n", str.c_str());
        !          1979:        }
        !          1980:        return num;
        !          1981: }
        !          1982: 
        !          1983: /* 式を解析する */
        !          1984: bool
        !          1985: parse_expr(String& expr, ArrayString& out)
        !          1986: {
        !          1987:        ArrayString tokens;
        !          1988:        std::stack<String> stack;
        !          1989: 
        !          1990:        DPRINTF(D_PARSE, "parse_expr.0 expr |%s|\n", expr.c_str());
        !          1991: 
        !          1992:        /* トークンに分解 */
        !          1993:        if (!scan_expr(expr, tokens)) {
        !          1994:                error("scan error: '%s'\n", expr.c_str());
        !          1995:        }
        !          1996: 
        !          1997:        /* 中置記法を後置記法に変換 */
        !          1998:        for (int i = 0; i < tokens.size(); i++) {
        !          1999:                String token = tokens[i];
        !          2000:                const char *tok = token.c_str();
        !          2001: 
        !          2002:                if (strcmp(tok, "+") == 0 || strcmp(tok, "-") == 0) {
        !          2003:                        for (; stack.size() > 0 && stack.top()[0] != '('; ) {
        !          2004:                                out.push_back(stack.top());
        !          2005:                                stack.pop();
        !          2006:                        }
        !          2007:                        stack.push(token);
        !          2008: 
        !          2009:                } else if (strcmp(tok, "*") == 0 || strcmp(tok, "/") == 0) {
        !          2010:                        if (stack.size() > 0) {
        !          2011:                                if (stack.top()[0] == '*' || stack.top()[0] == '/') {
        !          2012:                                        out.push_back(stack.top());
        !          2013:                                        stack.pop();
        !          2014:                                }
        !          2015:                        }
        !          2016:                        stack.push(token);
        !          2017: 
        !          2018:                } else if (strcmp(tok, "(") == 0) {
        !          2019:                        stack.push(token);
        !          2020: 
        !          2021:                } else if (strcmp(tok, ")") == 0) {
        !          2022:                        for (; stack.size() > 0 && stack.top()[0] != '('; ) {
        !          2023:                                out.push_back(stack.top());
        !          2024:                                stack.pop();
        !          2025:                        }
        !          2026:                        if (stack.size() == 0) {
        !          2027:                                error("expression error\n");
        !          2028:                        }
        !          2029:                        stack.pop();
        !          2030: 
        !          2031:                } else {
        !          2032:                        int num;
        !          2033:                        if (parse_number(token, &num)) {
        !          2034:                                /* 数値に変換できたら、数値(の文字列型)を格納 */
        !          2035:                                out.push_back(num2hex(num));
        !          2036:                        } else {
        !          2037:                                /* 数値にできなければ(たぶん)ラベルのまま格納 */
        !          2038:                                out.push_back(token);
        !          2039:                        }
        !          2040:                }
        !          2041:        }
        !          2042: 
        !          2043:        for (; stack.size() > 0;) {
        !          2044:                out.push_back(stack.top());
        !          2045:                stack.pop();
        !          2046:        }
        !          2047: 
        !          2048:        DPRINTF(D_PARSE, "parse_expr.3 expr");
        !          2049:        for (int i = 0; i < out.size(); i++) {
        !          2050:                DPRINTN(D_PARSE, "%c%s", (i==0)?'=':' ', out[i].c_str());
        !          2051:        }
        !          2052:        DPRINTN(D_PARSE, "\n");
        !          2053: 
        !          2054:        return true;
        !          2055: }
        !          2056: 
        !          2057: /*
        !          2058:  * 字句解析。expr をトークンごとに分解して tokens に入れて返す。
        !          2059:  */
        !          2060: bool
        !          2061: scan_expr(String& expr, ArrayString& tokens)
        !          2062: {
        !          2063: #if defined(_MSC_VER)
        !          2064:        char buf[BUFSIZE];
        !          2065: #else
        !          2066:        char buf[expr.size() + 1];
        !          2067: #endif
        !          2068:        char *s = NULL; /* shut up gcc */
        !          2069:        char *p;
        !          2070:        int c;
        !          2071:        enum {
        !          2072:                INIT,
        !          2073:                LABEL,
        !          2074:                DIGIT,
        !          2075:                HEX,
        !          2076:        } state;
        !          2077: 
        !          2078: #if defined(_MSC_VER)
        !          2079:        strncpy(buf, expr.c_str(), sizeof(buf) - 1);
        !          2080:        buf[sizeof(buf) - 1] = '\0';
        !          2081: #else
        !          2082:        strcpy(buf, expr.c_str());
        !          2083: #endif
        !          2084: 
        !          2085:        state = INIT;
        !          2086:        for (p = buf; *p; p++) {
        !          2087:                c = (int)*p;
        !          2088: 
        !          2089:                switch (state) {
        !          2090:                 case LABEL:    /* ラベルの2文字目以降 */
        !          2091:                        if (isalpha(c) || isdigit(c) || c == '_') {
        !          2092:                                continue;
        !          2093:                        }
        !          2094:                        break;
        !          2095:                 case DIGIT:    /* 数字の2文字目以降 */
        !          2096:                        if (isdigit(c)) {
        !          2097:                                continue;
        !          2098:                        }
        !          2099:                        break;
        !          2100:                 case HEX:              /* 16進の2文字目以降 */
        !          2101:                        if (isxdigit(c)) {
        !          2102:                                continue;
        !          2103:                        }
        !          2104:                        break;
        !          2105: 
        !          2106:                 case INIT:             /* 1文字目 */
        !          2107:                 init:
        !          2108:                        s = p;
        !          2109:                        if (isspace(c)) {
        !          2110:                                continue;
        !          2111:                        } else if (isalpha(c) || c == '_') {
        !          2112:                                state = LABEL;
        !          2113:                        } else if (isdigit(c)) {
        !          2114:                                state = DIGIT;
        !          2115:                        } else if (c == '$') {
        !          2116:                                state = HEX;
        !          2117:                        } else if (strchr("+-*/()", c)) {
        !          2118:                                /* 記号は1文字で確定する */
        !          2119:                                String token(s, 1);
        !          2120:                                tokens.push_back(token);
        !          2121:                                /* INIT状態のまま次の文字へ */
        !          2122:                                continue;
        !          2123:                        } else {
        !          2124:                                error("syntax error\n");
        !          2125:                        }
        !          2126:                        continue;
        !          2127:                }
        !          2128: 
        !          2129:                /* 1文字前までが1語句だった */
        !          2130:                String token(s, p - s);
        !          2131:                tokens.push_back(token);
        !          2132:                /* 今指してるのは次語句の先頭なので、この文字のまま INIT へ */
        !          2133:                state = INIT;
        !          2134:                goto init;
        !          2135:        }
        !          2136: 
        !          2137:        /* 状態を残したまま最後の文字まで来たら最後の語句を切り出す */
        !          2138:        if (state != INIT) {
        !          2139:                String token(s);
        !          2140:                tokens.push_back(token);
        !          2141:        }
        !          2142: 
        !          2143:        return true;
        !          2144: }
        !          2145: 
        !          2146: /* 計算途中の式をリストに追加 */
        !          2147: void
        !          2148: add_expr(int pos, reftype_t type, ArrayString& expr)
        !          2149: {
        !          2150:        REF *ref = new REF;
        !          2151: 
        !          2152:        ref->pos = pos;
        !          2153:        ref->line = ::line;
        !          2154:        ref->type = type;
        !          2155:        ref->expr = expr;
        !          2156:        DPRINTN_ref(D_EXPR, ref);
        !          2157: 
        !          2158:        ref_list.push_back(ref);
        !          2159: }
        !          2160: 
        !          2161: /* デバッグ表示 */
        !          2162: void
        !          2163: DPRINTN_ref(int debugflag, REF *ref)
        !          2164: {
        !          2165:        DPRINTF(debugflag, "REF line=%d pos=%d($%06x) type=%d ",
        !          2166:                ref->line, ref->pos, origin + ref->pos, (int)ref->type);
        !          2167:        DPRINTN_expr(debugflag, ref->expr);
        !          2168:        DPRINTN(debugflag, "\n");
        !          2169: }
        !          2170: 
        !          2171: /* デバッグ表示 */
        !          2172: void
        !          2173: DPRINTN_expr(int debugflag, ArrayString& expr)
        !          2174: {
        !          2175:        DPRINTN(debugflag, "expr");
        !          2176:        for (int i = 0; i < expr.size(); i++) {
        !          2177:                DPRINTN(debugflag, "%c%s", (i == 0)?'=':' ', expr[i].c_str());
        !          2178:        }
        !          2179: }
        !          2180: 
        !          2181: /*
        !          2182:  * 式を計算する。
        !          2183:  * error_stop が真ならラベルが解決できないのをエラーにする。
        !          2184:  * 1st stage では false、2nd stage では true にする。
        !          2185:  * false でラベルが解決できなければ false を返すだけ。
        !          2186:  */
        !          2187: bool
        !          2188: calc_expr(ArrayString& expr, uint32_t& retval, bool error_stop)
        !          2189: {
        !          2190:        uint32_t val;
        !          2191:        uint32_t v1, v2;
        !          2192:        int i;
        !          2193: 
        !          2194:        DPRINTF(D_EXPR, "calc_expr.0 ");
        !          2195:        DPRINTN_expr(D_EXPR, expr);
        !          2196:        DPRINTN(D_EXPR, "\n");
        !          2197: 
        !          2198:        /* まずラベルが解決できるか */
        !          2199:        for (i = 0; i < expr.size(); i++) {
        !          2200:                String token = expr[i];
        !          2201:                if (isalpha((int)token[0])) {
        !          2202:                        int intval;
        !          2203:                        if (parse_number(token, &intval)) {
        !          2204:                                /* 見付かったので数値に差し替える */
        !          2205:                                expr[i] = num2hex(intval);
        !          2206:                                DPRINTF(D_EXPR, "calc_expr.1 '%s' is %s\n",
        !          2207:                                        token.c_str(), expr[i].c_str());
        !          2208:                        } else {
        !          2209:                                /* 見付からなかった */
        !          2210:                                if (error_stop) {
        !          2211:                                        error("undefined label: %s\n", token.c_str());
        !          2212:                                } else {
        !          2213:                                        DPRINTF(D_EXPR, "calc_expr.1 '%s' not resolved, quit\n",
        !          2214:                                                token.c_str());
        !          2215:                                        return false;
        !          2216:                                }
        !          2217:                        }
        !          2218:                }
        !          2219:        }
        !          2220:        DPRINTF(D_EXPR, "calc_expr.2 ");
        !          2221:        DPRINTN_expr(D_EXPR, expr);
        !          2222:        DPRINTN(D_EXPR, "\n");
        !          2223: 
        !          2224:        /* ラベルが全部解決できたので計算する */
        !          2225:        std::stack<uint32_t> stack;
        !          2226:        for (i = 0; i < expr.size(); i++) {
        !          2227:                String token = expr[i];
        !          2228:                if (token[0] == '$') {
        !          2229:                        /* 取り出したのが数値ならスタックに積む */
        !          2230:                        val = (uint32_t)tonumber(token);
        !          2231:                        stack.push(val);
        !          2232: 
        !          2233:                } else {
        !          2234:                        /* 取り出したのが演算子ならスタックから2つ取って.. */
        !          2235:                        v2 = stack.top();
        !          2236:                        stack.pop();
        !          2237:                        v1 = stack.top();
        !          2238:                        stack.pop();
        !          2239: 
        !          2240:                        /* 計算 */
        !          2241:                        if (token[0] == '+') {
        !          2242:                                val = v1 + v2;
        !          2243:                        } else if (token[0] == '-') {
        !          2244:                                val = v1 - v2;
        !          2245:                        } else if (token[0] == '*') {
        !          2246:                                val = v1 * v2;
        !          2247:                        } else if (token[0] == '/') {
        !          2248:                                val = v1 / v2;
        !          2249:                        } else {
        !          2250:                                error("unknown operator: %s\n", token.c_str());
        !          2251:                        }
        !          2252: 
        !          2253:                        /* それを再び積む */
        !          2254:                        stack.push(val);
        !          2255:                }
        !          2256:        }
        !          2257: 
        !          2258:        retval = stack.top();
        !          2259: DPRINTF(D_EXPR, "calc_expr.3 ret=$%x\n", retval);
        !          2260:        return true;
        !          2261: }
        !          2262: 
        !          2263: /* 文字列を解析 */
        !          2264: String
        !          2265: parse_string(String& src)
        !          2266: {
        !          2267:        String dst;
        !          2268:        enum {
        !          2269:                OUTER = 0,
        !          2270:                PLAIN,
        !          2271:                ESC,
        !          2272:        } state;
        !          2273: 
        !          2274:        state = OUTER;
        !          2275:        for (int i = 0; i < src.size(); i++) {
        !          2276:                int c = (int)(src[i]);
        !          2277:                switch (state) {
        !          2278:                 case OUTER:
        !          2279:                        if (isspace(c)) {
        !          2280:                                ;
        !          2281:                        } else if (c == '\x22') {
        !          2282:                                state = PLAIN;
        !          2283:                        } else {
        !          2284:                                error("syntax error around string: %s", src.c_str());
        !          2285:                        }
        !          2286:                        break;
        !          2287: 
        !          2288:                 case PLAIN:
        !          2289:                        if (c == '\x22') {
        !          2290:                                state = OUTER;
        !          2291:                        } else if (c == '\\') {
        !          2292:                                state = ESC;
        !          2293:                        } else {
        !          2294:                                dst.push_back(c);
        !          2295:                        }
        !          2296:                        break;
        !          2297: 
        !          2298:                 case ESC:
        !          2299:                        if (c == 'n') {
        !          2300:                                dst.push_back('\n');
        !          2301:                        } else if (c == 't') {
        !          2302:                                dst.push_back('\t');
        !          2303:                        } else {
        !          2304:                                dst.push_back(c);
        !          2305:                        }
        !          2306:                        /* XXX \xHH 追加のこと */
        !          2307:                        state = PLAIN;
        !          2308:                        break;
        !          2309:                }
        !          2310:        }
        !          2311:        if (state != OUTER) {
        !          2312:                error("syntax error in string: %s\n", src.c_str());
        !          2313:        }
        !          2314: 
        !          2315:        return dst;
        !          2316: }
        !          2317: 
        !          2318: /* 文字コードを UTF-8 から Shift_JIS に変換 */
        !          2319: String
        !          2320: convert_charset(String& src)
        !          2321: {
        !          2322: #if defined(_WIN32)
        !          2323:        /*
        !          2324:         * Win32 API を使う
        !          2325:         */
        !          2326:        int size;
        !          2327:        WCHAR wsrc[BUFSIZE];
        !          2328:        char mdst[BUFSIZE];
        !          2329: 
        !          2330:        /* まず(UTF-8の)ワイド文字列に変換 */
        !          2331:        size = MultiByteToWideChar(CP_UTF8, 0, src.c_str(), -1, NULL, 0);
        !          2332:        MultiByteToWideChar(CP_UTF8, 0, src.c_str(), -1, wsrc, size);
        !          2333: 
        !          2334:        /* Shift_JIS のマルチバイト文字に変換 */
        !          2335:        size = WideCharToMultiByte(932, 0, wsrc, -1, NULL, 0, 0, NULL);
        !          2336:        WideCharToMultiByte(932, 0, wsrc, -1, mdst, size, 0, NULL);
        !          2337: 
        !          2338:        String dst(mdst);
        !          2339:        return dst;
        !          2340: 
        !          2341: #elif defined(IASM_USE_iconv)
        !          2342:        /*
        !          2343:         * iconv(3) を使う
        !          2344:         */
        !          2345:        iconv_t cd;
        !          2346:        char dstbuf[src.size() * 2];    /* 適当 */
        !          2347:        const char *srcptr;
        !          2348:        char *dstptr;
        !          2349:        size_t srcsize;
        !          2350:        size_t dstsize;
        !          2351:        size_t r;
        !          2352: 
        !          2353:        cd = iconv_open("Shift_JIS", "UTF-8");
        !          2354:        if (cd == NULL) {
        !          2355:                return src;
        !          2356:        }
        !          2357: 
        !          2358:        srcptr = src.c_str();
        !          2359:        srcsize = src.size();
        !          2360:        memset(dstbuf, 0, sizeof(dstbuf));
        !          2361:        dstptr = dstbuf;
        !          2362:        dstsize = sizeof(dstbuf);
        !          2363:        r = iconv(cd, (iconv_src_t)&srcptr, &srcsize, &dstptr, &dstsize);
        !          2364:        if (r == -1) {
        !          2365:                error("cannot conversion string: %s\n", srcptr);
        !          2366:        }
        !          2367:        if (r > 0) {
        !          2368:                error("invalid charactor found: %s\n", srcptr);
        !          2369:        }
        !          2370: 
        !          2371:        iconv_close(cd);
        !          2372: 
        !          2373:        String dst(dstbuf);
        !          2374:        return dst;
        !          2375: 
        !          2376: #elif defined(IASM_USE_wxWidgets)
        !          2377:        /*
        !          2378:         * wxWidgets の wxCSConv を使う
        !          2379:         */
        !          2380:        char buf[src.size() * 2];       /* 適当 */
        !          2381: 
        !          2382:        wxString wstr(src.c_str(), wxConvUTF8);
        !          2383:        wxCSConv conv(wxT("SHIFT_JIS"));
        !          2384:        conv.WC2MB(buf, wstr.wc_str(), sizeof(buf));
        !          2385: 
        !          2386:        String dst(buf);
        !          2387:        return dst;
        !          2388: 
        !          2389: #else
        !          2390:        /*
        !          2391:         * 文字コード変換ライブラリがない場合は何もしない
        !          2392:         */
        !          2393:        return src;
        !          2394: #endif
        !          2395: }
        !          2396: 
        !          2397: /* デバッグ表示 (ap版) */
        !          2398: void
        !          2399: DPRINTV(int flag, const char *fmt, va_list ap)
        !          2400: {
        !          2401:        if ((debug & flag)) {
        !          2402:                vprintf(fmt, ap);
        !          2403:        }
        !          2404: }
        !          2405: 
        !          2406: /* デバッグ表示 (行頭のマークなし) */
        !          2407: void
        !          2408: DPRINTN(int flag, const char *fmt, ...)
        !          2409: {
        !          2410:        va_list ap;
        !          2411: 
        !          2412:        va_start(ap, fmt);
        !          2413:        DPRINTV(flag, fmt, ap);
        !          2414:        va_end(ap);
        !          2415: }
        !          2416:        
        !          2417: /* デバッグ表示 (行頭のマーク付き) */
        !          2418: void
        !          2419: DPRINTF(int flag, const char *fmt, ...)
        !          2420: {
        !          2421:        va_list ap;
        !          2422:        int ch;
        !          2423: 
        !          2424:        switch (flag) {
        !          2425:         case D_INOUT:
        !          2426:                ch = '|';
        !          2427:                break;
        !          2428:         case D_EA:
        !          2429:                ch = 'A';
        !          2430:                break;
        !          2431:         case D_LABEL:
        !          2432:                ch = 'L';
        !          2433:                break;
        !          2434:         case D_PARSE:
        !          2435:                ch = 'P';
        !          2436:                break;
        !          2437:         case D_STAGE:
        !          2438:                ch = ' ';
        !          2439:                break;
        !          2440:         case D_EXPR:
        !          2441:                ch = 'E';
        !          2442:                break;
        !          2443:         case D_SCAN:
        !          2444:                ch = 'S';
        !          2445:                break;
        !          2446:         default:
        !          2447:                ch = '?';
        !          2448:                break;
        !          2449:        }
        !          2450:        DPRINTN(flag, "%c ", ch);
        !          2451: 
        !          2452:        va_start(ap, fmt);
        !          2453:        DPRINTV(flag, fmt, ap);
        !          2454:        va_end(ap);
        !          2455: }
        !          2456: 
        !          2457: /* アセンブルエラー */
        !          2458: void
        !          2459: error(const char *fmt, ...)
        !          2460: {
        !          2461:        char buf[1024];
        !          2462:        va_list ap;
        !          2463: 
        !          2464:        va_start(ap, fmt);
        !          2465:        vsnprintf(buf, sizeof(buf), fmt, ap);
        !          2466:        va_end(ap);
        !          2467: 
        !          2468:        /* デバッグモードなら stdout にも出力しないと分かりづらい */
        !          2469:        DPRINTN(D_STAGE, "%s:%d:%s", current_infile, line, buf);
        !          2470:        fprintf(stderr, "%s:%d:%s", current_infile, line, buf);
        !          2471: 
        !          2472:        /* 出力しかけのファイルは消しておく (次のビルドのため) */
        !          2473:        if (outfile) {
        !          2474:                fclose(outfp);
        !          2475:                unlink(outfile);
        !          2476:                fprintf(stderr, "output file '%s' removed\n", outfile);
        !          2477:        }
        !          2478: 
        !          2479:        exit(1);
        !          2480: }
        !          2481: 
        !          2482: /* String の前後の空白を取り除く */
        !          2483: void
        !          2484: trim(String& str)
        !          2485: {
        !          2486:        ltrim(str);
        !          2487:        rtrim(str);
        !          2488: }
        !          2489: 
        !          2490: /* String の先頭の空白を取り除く */
        !          2491: void
        !          2492: ltrim(String& str)
        !          2493: {
        !          2494:        while (isspace((int)str[0])) {
        !          2495:                str.erase(0, 1);
        !          2496:        }
        !          2497: }
        !          2498: 
        !          2499: /* String の末尾の空白を取り除く */
        !          2500: void
        !          2501: rtrim(String& str)
        !          2502: {
        !          2503:        for (int r = str.length() - 1; r >= 0; r--) {
        !          2504:                if (isspace((int)str[r])) {
        !          2505:                        str.erase(r);
        !          2506:                } else {
        !          2507:                        break;
        !          2508:                }
        !          2509:        }
        !          2510: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.