root/src/token.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opdtok
  2. addcerrlist_tok
  3. linetok

   1 #include "token.h"
   2 
   3 /**
   4  * @brief 「,」区切りの文字列から、オペランドのトークンを取得
   5  *
   6  * @return オペランドのトークン
   7  *
   8  * @param *str 「,」区切りの文字列
   9  */
  10 OPD *opdtok(const char *str);
  11 
  12 /**
  13  * @brief 行トークン取得のエラー定義
  14  */
  15 CERR cerr_linetok[] = {
  16     { 104, "label length is too long" },
  17     { 105, "no command in the line" },
  18 };
  19 
  20 /**
  21  * @brief オペランドトークン取得のエラー定義
  22  */
  23 static CERR cerr_opdtok[] = {
  24     { 117, "operand too many in DC" },
  25     { 118, "operand length too long" },
  26     { 121, "cannot get operand token" },
  27     { 123, "unclosed quote" },
  28 };
  29 
  30 OPD *opdtok(const char *str)
  31 {
  32     OPD *opd = malloc_chk(sizeof(OPD), "opd");
  33     char *tok, *p, sepc = ',';
  34     int i = 0, cnt_quote = 0;
  35     bool quoting = false;
  36 
  37     opd->opdc = 0;
  38     if(!str || !str[0]) {
  39         return opd;
  40     }
  41     tok = p = strdup_chk(str, "opdtok.p");
  42     do {
  43         /* オペランド数が多すぎる場合はエラー */
  44         if(opd->opdc >= OPDSIZE) {
  45             setcerr(117, "");    /* operand is too many */
  46             break;
  47         }
  48         /* 先頭が等号(=)の場合 */
  49         if(p[i] == '=') {
  50             i++;
  51         }
  52         /* 「'」の場合 */
  53         if(p[i] == '\'') {
  54             /* 「''」以外の場合はquote値を反転する */
  55             if(p[i+1] != '\'' && (quoting == false || p[i-1] != '\'')) {
  56                 quoting = !quoting;
  57             }
  58             /* 「'」をカウントする。「''」の場合は1をカウント */
  59             if(p[i+1] != '\'') {
  60                 cnt_quote++;
  61             }
  62         }
  63         if(quoting == true) {
  64             /* 「'」で開いたまま文字列が終了した場合 */
  65             if(!p[i]) {
  66                 setcerr(123, str);    /* unclosed quote */
  67                 break;
  68             }
  69             i++;
  70         } else {
  71             i += strcspn(p + i, ", ");
  72             if(i == 0) {
  73                 setcerr(121, "");    /* cannot get operand token */
  74                 break;
  75             }
  76             if(i - cnt_quote > OPDSIZE) {
  77                 setcerr(118, "");    /* operand length too long */
  78                 break;
  79             }
  80             sepc = p[i];
  81             opd->opdv[(opd->opdc)++] = strndup_chk(p, i, "opd->opdv[]");
  82             p += i + 1;
  83             i = cnt_quote = 0;
  84         }
  85     } while(sepc == ',');
  86     FREE(tok);
  87     return opd;
  88 }
  89 
  90 /* assemble.hで定義された関数群 */
  91 void addcerrlist_tok()
  92 {
  93     addcerrlist(ARRAYSIZE(cerr_linetok), cerr_linetok);
  94     addcerrlist(ARRAYSIZE(cerr_opdtok), cerr_opdtok);
  95 }
  96 
  97 CMDLINE *linetok(const char *line)
  98 {
  99     char *tok = NULL, *p = NULL;
 100     int i;
 101     CMDLINE *cmdl = NULL;
 102 
 103     assert(line);
 104     if(!line[0] || line[0] == '\n') {
 105         return NULL;
 106     }
 107     tok = p = strdup_chk(line, "tok");
 108     /* コメントを削除 */
 109     strip_casl2_comment(p);
 110     /* 文字列末尾の改行と空白を削除 */
 111     strip_end(p);
 112     /* 空行の場合、終了 */
 113     if(!p[0]) {
 114         goto linetokfin;
 115     }
 116     cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
 117 
 118     /* ラベルの取得 */
 119     /* 行の先頭が空白またはタブの場合、ラベルは空 */
 120     if((i = strcspn(p, " \t")) == 0) {
 121         cmdl->label = strdup_chk("", "cmdl->label");
 122     } else {
 123         cmdl->label = strndup_chk(p, i, "cmdl->label");
 124         /* ラベルの文字列が長すぎる場合はエラー */
 125         if(i > LABELSIZE) {
 126             setcerr(104, cmdl->label);    /* label length is too long */
 127             FREE(cmdl->label);
 128             goto linetokfin;
 129         }
 130     }
 131 
 132     /* 命令の取得 */
 133     /* 文字列先頭をラベルの次の文字に移動 */
 134     p += i;
 135     /* 文字列先頭を、ラベルと命令の間の空白の後ろに移動 */
 136     p += strspn(p, " \t");
 137     /* 命令がない場合は、終了 */
 138     if(!p[0]) {
 139         if(cmdl->label) {      /* ラベルが定義されていて命令がない場合はエラー */
 140             setcerr(105, "");    /* no command in the line */
 141         }
 142         FREE(cmdl->label);
 143         FREE(cmdl);
 144         goto linetokfin;
 145     }
 146     /* 命令取得の実行 */
 147     i = strcspn(p, " \t");
 148     cmdl->cmd = strndup_chk(p, i, "cmdl.cmd");
 149 
 150     /* オペランドの取得 */
 151     /* 文字列先頭を、命令の次の文字に移動 */
 152     p += i;
 153     /* 文字列先頭を、命令とオペランドの間の空白の後ろに移動 */
 154     p += strspn(p, " \t");
 155     /* オペランド取得の実行 */
 156     cmdl->opd = opdtok(p);
 157 linetokfin:
 158     FREE(tok);
 159     return cmdl;
 160 }

/* [<][>][^][v][top][bottom][index][help] */