nasm.c

来自「开源的nasm编译器源码,研究编译器原理很有帮且」· C语言 代码 · 共 1,683 行 · 第 1/4 页

C
1,683
字号
               switch (i) {               case 1:               /* [SEGMENT n] */                  seg = ofmt->section (value, pass2, &sb);                  if (seg == NO_SEG) {                     report_error (pass1==1 ? ERR_NONFATAL : ERR_PANIC,                                    "segment name `%s' not recognised",                                    value);                  } else {                     in_abs_seg = FALSE;                     location.segment = seg;                  }                  break;               case 2:               /* [EXTERN label:special] */                  if (*value == '$') value++;   /* skip initial $ if present */                  if (pass0 == 2) {                        q = value;                        while (*q && *q != ':')                           q++;                        if (*q == ':') {                           *q++ = '\0';                           ofmt->symdef(value, 0L, 0L, 3, q);                        }                  } else if (pass == 1) {   /* pass == 1 */                        q = value;                        validid = TRUE;                        if (!isidstart(*q))                           validid = FALSE;                        while (*q && *q != ':') {                           if (!isidchar(*q))                                 validid = FALSE;                           q++;                        }                        if (!validid) {                           report_error (ERR_NONFATAL,                                          "identifier expected after EXTERN");                           break;                        }                        if (*q == ':') {                           *q++ = '\0';                           special = q;                        } else                           special = NULL;                        if (!is_extern(value)) {   /* allow re-EXTERN to be ignored */                           int temp = pass0;                           pass0 = 1;	/* fake pass 1 in labels.c */                           declare_as_global (value, special, report_error);                           define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE,                                          ofmt, report_error);                           pass0 = temp;                        }                  } /* else  pass0 == 1 */                  break;               case 3:               /* [BITS bits] */                  sb = get_bits(value);                  break;               case 4:               /* [GLOBAL symbol:special] */                  if (*value == '$') value++;   /* skip initial $ if present */                  if (pass0 == 2) { /* pass 2 */                        q = value;                        while (*q && *q != ':')                           q++;                        if (*q == ':') {                           *q++ = '\0';                           ofmt->symdef(value, 0L, 0L, 3, q);                        }                  } else if (pass2 == 1) { /* pass == 1 */                        q = value;                        validid = TRUE;                        if (!isidstart(*q))                           validid = FALSE;                        while (*q && *q != ':') {                           if (!isidchar(*q))                                 validid = FALSE;                           q++;                        }                        if (!validid) {                           report_error (ERR_NONFATAL,                                          "identifier expected after GLOBAL");                           break;                        }                        if (*q == ':') {                           *q++ = '\0';                           special = q;                        } else                           special = NULL;                        declare_as_global (value, special, report_error);                  } /* pass == 1 */                  break;               case 5:               /* [COMMON symbol size:special] */                  if (*value == '$') value++;   /* skip initial $ if present */                  if (pass0 == 1) {                        p = value;                        validid = TRUE;                        if (!isidstart(*p))                           validid = FALSE;                        while (*p && !isspace(*p)) {                           if (!isidchar(*p))                                 validid = FALSE;                           p++;                        }                        if (!validid) {                           report_error (ERR_NONFATAL,                                          "identifier expected after COMMON");                           break;                        }                        if (*p) {                           long size;                           while (*p && isspace(*p))                                 *p++ = '\0';                           q = p;                           while (*q && *q != ':')                                 q++;                           if (*q == ':') {                                 *q++ = '\0';                                 special = q;                           } else                                 special = NULL;                           size = readnum (p, &rn_error);                           if (rn_error)                                 report_error (ERR_NONFATAL, "invalid size specified"                                             " in COMMON declaration");                           else                                 define_common (value, seg_alloc(), size,                                                special, ofmt, report_error);                        } else                           report_error (ERR_NONFATAL, "no size specified in"                                          " COMMON declaration");                  } else if (pass0 == 2) { /* pass == 2 */                        q = value;                        while (*q && *q != ':') {                           if (isspace(*q))                                 *q = '\0';                           q++;                        }                        if (*q == ':') {                           *q++ = '\0';                           ofmt->symdef(value, 0L, 0L, 3, q);                        }                  }                  break;               case 6:                       /* [ABSOLUTE address] */                  stdscan_reset();                  stdscan_bufptr = value;                  tokval.t_type = TOKEN_INVALID;                  e = evaluate(stdscan, NULL, &tokval, NULL, pass2, report_error,                              NULL);                  if (e) {                     if (!is_reloc(e))                           report_error (pass0==1 ? ERR_NONFATAL : ERR_PANIC,                                 "cannot use non-relocatable expression as "                                 "ABSOLUTE address");                     else {			 abs_seg = reloc_seg(e);			 abs_offset = reloc_value(e);                     }                  } else                     if (pass==1) abs_offset = 0x100;/* don't go near zero in case of / */                     else report_error (ERR_PANIC, "invalid ABSOLUTE address "                                    "in pass two");                  in_abs_seg = TRUE;                  location.segment = NO_SEG;                  break;               case 7:    /* DEBUG       */                  p = value;                  q = debugid;                  validid = TRUE;                  if (!isidstart(*p))                     validid = FALSE;                  while (*p && !isspace(*p)) {                     if (!isidchar(*p))                           validid = FALSE;                     *q++ = *p++;                  }                  *q++ = 0;                  if (!validid) {                     report_error (pass==1 ? ERR_NONFATAL : ERR_PANIC,                                    "identifier expected after DEBUG");                     break;                  }                  while (*p && isspace(*p)) p++;                  if (pass==pass_max) ofmt->current_dfmt->debug_directive (debugid, p);                  break;               case 8:			/* [WARNING {+|-}warn-name] */                  if (pass1 == 1) {		     while (*value && isspace(*value))		        value++;                     if (*value == '+' || *value == '-') {		        validid = (*value == '-') ? TRUE : FALSE;		        value++;		     } else		        validid = FALSE;		     for (i=1; i<=ERR_WARN_MAX; i++)		        if (!nasm_stricmp(value, suppressed_names[i]))			    break;		     if (i <= ERR_WARN_MAX)		        suppressed[i] = validid;		     else		        report_error (ERR_NONFATAL, "invalid warning id in WARNING directive");	          }		  break;               case 9:  /* cpu */                  cpu = get_cpu (value);                  break;               case 10:        /* fbk 9/2/00 */       /* [LIST {+|-}] */                   while (*value && isspace(*value))                       value++;                   if (*value == '+') {                       user_nolist = 0;		     }                     else {                          if (*value == '-') {                          user_nolist = 1;                          }                          else {                              report_error (ERR_NONFATAL, "invalid parameter to \"list\" directive");                          }                      }                  break;               default:                  if (!ofmt->directive (directive, value, pass2))                     report_error (pass1==1 ? ERR_NONFATAL : ERR_PANIC,                              "unrecognised directive [%s]",                              directive);               }         }         else         /* it isn't a directive */         {               parse_line (pass1, line, &output_ins,                           report_error, evaluate,                           def_label);               if (!(optimizing>0) && pass == 2) {                  if (forwref != NULL && globallineno == forwref->lineno) {                     output_ins.forw_ref = TRUE;                     do {                        output_ins.oprs[forwref->operand].opflags |= OPFLAG_FORWARD;                        forwref = saa_rstruct (forwrefs);                     } while (forwref != NULL && forwref->lineno == globallineno);                  } else                     output_ins.forw_ref = FALSE;               }               if (!(optimizing>0) && output_ins.forw_ref)               {                  if (pass == 1) {                        for(i = 0; i < output_ins.operands; i++)                        {                           if (output_ins.oprs[i].opflags & OPFLAG_FORWARD)                           {                                    struct forwrefinfo *fwinf =                                       (struct forwrefinfo *)saa_wstruct(forwrefs);                                 fwinf->lineno = globallineno;                                 fwinf->operand = i;                           }                        }                  } else { /* pass == 2 */                        /*                        * Hack to prevent phase error in the code                        *   rol ax,x                        *   x equ 1                        *                        * If the second operand is a forward reference,                        * the UNITY property of the number 1 in that                        * operand is cancelled. Otherwise the above                        * sequence will cause a phase error.                        *                        * This hack means that the above code will                        * generate 286+ code.                        *                        * The forward reference will mean that the                        * operand will not have the UNITY property on                        * the first pass, so the pass behaviours will                        * be consistent.                        */                        if (output_ins.operands >= 2 &&                        (output_ins.oprs[1].opflags & OPFLAG_FORWARD))                        {                           output_ins.oprs[1].type &= ~(ONENESS|BYTENESS);                        }                  } /* pass == 2 */               } /*  forw_ref */               if (output_ins.opcode == I_EQU) {                     if (pass1 == 1)                     {                        /*                        * Special `..' EQUs get processed in pass two,                        * except `..@' macro-processor EQUs which are done                        * in the normal place.                        */                        if (!output_ins.label)                           report_error (ERR_NONFATAL,                                          "EQU not preceded by label");                        else if (output_ins.label[0] != '.' ||                                 output_ins.label[1] != '.' ||                                 output_ins.label[2] == '@')                        {                           if (output_ins.operands == 1 &&                                 (output_ins.oprs[0].type & IMMEDIATE) &&                                 output_ins.oprs[0].wrt == NO_SEG)                           {                              int isext = output_ins.oprs[0].opflags & OPFLAG_EXTERN;                              def_label (output_ins.label,					 output_ins.oprs[0].segment,					 output_ins.oprs[0].offset,					 NULL, FALSE, isext, ofmt, report_error);                           }                           else if (output_ins.operands == 2 &&                                       (output_ins.oprs[0].type & IMMEDIATE) &&                                       (output_ins.oprs[0].type & COLON) &&                                       output_ins.oprs[0].segment == NO_SEG &&                                       output_ins.oprs[0].wrt == NO_SEG &&                                       (output_ins.oprs[1].type & IMMEDIATE) &&                                       output_ins.oprs[1].segment == NO_SEG &&                                       output_ins.oprs[1].wrt == NO_SEG)                           {                                 def_label (output_ins.label,                                             output_ins.oprs[0].offset | SEG_ABS,                                             output_ins.oprs[1].offset,                                             NULL, FALSE, FALSE, ofmt, report_error);                           }                           else                                 report_error(ERR_NONFATAL, "bad syntax for EQU");                        }                     } else {  /* pass == 2 */                        /*                        * Special `..' EQUs get processed here, except                        * `..@' macro processor EQUs which are done above.                        */                        if (output_ins.label[0] == '.' &&                           output_ins.label[1] == '.' &&                           output_ins.label[2] != '@')                        {                           if (output_ins.operands == 1 &&                                 (output_ins.oprs[0].type & IMMEDIATE)) {                                 define_label (output_ins.label,                                             output_ins.oprs[0].segment,                                             output_ins.oprs[0].offset,                                             NULL, FALSE, FALSE, ofmt, report_error);                           }                           else if (output_ins.operands == 2 &&                                       (output_ins.oprs[0].type & IMMEDIATE) &&                                       (output_ins.oprs[0].type & COLON) &&                                       output_ins.oprs[0].segment == NO_SEG &&                                       (output_ins.oprs[1].type & IMMEDIATE) &&                                       output_ins.oprs[1].segment == NO_SEG)                           {                                 define_label (output_ins.label,                                             output_ins.oprs[0].offset | SEG_ABS,                                             output_ins.oprs[1].offset,                                             NULL, FALSE, FALSE, ofmt, report_error);                           }                           else                                 report_error(ERR_NONFATAL, "bad syntax for EQU");                        }                     }  /* pass == 2 */               } else { /* instruction isn't an EQU */                     if (pass1 == 1) {                        long l = insn_size (location.segment, offs, sb, cpu,                                          &output_ins, report_error);                        /* if (using_debug_info)  && output_ins.opcode != -1)*/                        if (using_debug_info)  /* fbk 03/25/01 */                        {                           /* this is done here so we can do debug type info */                           long typeinfo = TYS_ELEMENTS(output_ins.operands);                           switch (output_ins.opcode) {                                    case I_RESB:                                        typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;                                        break;                                    case I_RESW:                                        typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;                                        break;                                    case I_RESD:                                        typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;                                        break;                                    case I_RESQ:                                        typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;                                        break;                                    case I_REST:                                        typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;                                        break;                                    case I_DB:                                        typeinfo |= TY_BYTE;                                        break;                                    case I_DW:                                        typeinfo |= TY_WORD;                                        break;                                    case I_DD:                                       if (output_ins.eops_float)                                                typeinfo |= TY_FLOAT;                                       else                                                typeinfo |= TY_DWORD;                                       break;                                    case I_DQ:                                       typeinfo |= TY_QWORD;                                       break;                                    case I_DT:                                       typeinfo |= TY_TBYTE;                                       break;                                    default:                                       typeinfo = TY_LABEL;                           }                           ofmt->current_dfmt->debug_typevalue(typeinfo);                        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?