Esempio n. 1
0
OPD *opdtok(const char *str)
{
    OPD *opd = malloc_chk(sizeof(OPD), "opd");
    char *p, *q, *r, *sepp;     /* pは文字列全体の先頭位置、qはトークンの先頭位置、rは文字の位置 */
    int sepc = ',', rcnt = 0;
    bool quoting = false;

    opd->opdc = 0;
    if(str == NULL) {
        return opd;
    }
    p = q = r = strdup_chk(str, "opdtok.p");
    do {
        /* オペランド数が多すぎる場合はエラー */
        if(opd->opdc >= OPDSIZE) {
            setcerr(117, "");    /* operand is too many */
            break;
        }
        /* 先頭が等号(=)の場合 */
        if(*r == '=') {
            r++;
        }
        /* 「'」の場合 */
        if(*r == '\'') {
            /* 「''」以外の場合はquote値を反転 */
            if(*(r+1) != '\'' && !(q < r && *(r-1) == '\'')) {
                quoting = !quoting;
            }
            /* 文字列の長さを数える。「'」の場合は数えない */
            if(*(r+1) != '\'') {
                rcnt++;
            }
        }
        if(quoting == true) {
            /* 閉じ「'」がないまま文字列が終了した場合 */
            if(*r == '\0') {
                setcerr(123, str);    /* unclosed quote */
                break;
            }
            r++;
        } else {
            sepp = r + strcspn(r, ", ");
            sepc = *sepp;
            *sepp = '\0';
            if(*q == '\0') {
                setcerr(121, "");    /* cannot get operand token */
                break;
            }
            if(strlen(q) - rcnt > OPDSIZE) {
                setcerr(118, "");    /* operand length too long */
                break;
            }
            opd->opdv[(++opd->opdc)-1] = strdup_chk(q, "opd.opdv[]");
            q = r = sepp + 1;
            rcnt = 0;
        }
    } while(sepc == ',');
    FREE(p);
    return opd;
}
Esempio n. 2
0
char *strdup_chk(const char *s, const char *tag)
{
    assert(s != NULL);
    char *t = malloc_chk(strlen(s) + 1, tag);
    strcpy(t, s);
    return t;
}
Esempio n. 3
0
void addcerrlist(int cerrc, CERR cerrv[])
{
    int i;
    CERRLIST *p = NULL, *q = malloc_chk(sizeof(CERRLIST), "cerrlist");

    assert(cerrc > 0 && cerrv != NULL);
    for(i = 0; i < cerrc; i++) {
        if(p == NULL) {
            p = q;
        } else {
            p = p->next = malloc_chk(sizeof(CERRLIST), "cerrlist.next");
        }
        p->cerr = &cerrv[i];
        p->next = NULL;
    }
    p->next = cerrlist;
    cerrlist = q;
}
Esempio n. 4
0
void setcerr(int num, const char *str)
{
    /* 現在のエラー番号を設定  */
    cerr->num = num;
    /* 現在のエラーメッセージを設定 */
    cerr->msg = malloc_chk(CERRMSGSIZE + 1, "cerr.msg");
    if(0 < strlen(str) && strlen(str) <= CERRSTRSIZE) {
        sprintf(cerr->msg, "%s: %s", str, getcerrmsg(cerr->num));
    } else {
        strcpy(cerr->msg, getcerrmsg(cerr->num));
    }
}
Esempio n. 5
0
char *strndup_chk(const char *s, size_t len, const char *tag)
{
    assert(s != NULL);
    char *t = NULL;

    if(len < strlen(s)) {
        t = malloc_chk(len + 1, tag);
        strncpy(t, s, len);
        t[len] = '\0';
    } else {
        t = strdup_chk(s, tag);
    }
    return t;
}
Esempio n. 6
0
int main(){
    int i, j;
    int code[] = {
        101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
        111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
        121, 122, 123, 124, 201, 202, 203, 204, 205, 206, 207, 999
    };
    const char *str[] = {NULL, "foobar"};
    addcerrlist(ARRAYSIZE(cerr_utest), cerr_utest);
    /* エラーの初期化 */
    cerr = malloc_chk(sizeof(CERR), "cerr");
    for(i = 0; i < ARRAYSIZE(str); i++) {
        for(j = 0; j < ARRAYSIZE(code); j++) {
            setcerr(code[j], str[i]);
            printf("%d: %s - %d\t%s\n", code[j], str[i], cerr->num, cerr->msg);
        }
    }
    freecerr();
    return 0;
}
Esempio n. 7
0
void cerr_init()
{
    cerr = malloc_chk(sizeof(CERR), "cerr");
    cerr->num = 0;
}
Esempio n. 8
0
errCode genTextures(const char *rootDir, const sFileList *files, sTex ***dynarrTextures){
	static const size_t BUFFLEN = 1024;

	int numTexs=0;
	int idxFile = files->num;
	sTex *refTex;

	if(idxFile <= 0 || rootDir == NULL || rootDir[0] == '\0' || dynarrTextures == NULL)
		return PROBLEM;

	size_t lenRootDir = strlen(rootDir);
	char filePath[BUFFLEN];
	FILE *handFile;
	png_byte header[PNGHEAD_SIZE];

	strncpy(filePath, rootDir, 1024);
	if(lenRootDir>0 && filePath[lenRootDir-1]!='/'){
		filePath[lenRootDir] = '/';
		lenRootDir += 1;
	}

	while(idxFile > 0){
		--idxFile;

		strncpy(&filePath[lenRootDir], files->dynarrFiles[idxFile], 1024 - lenRootDir);

		handFile = fopen(filePath, "rb");

		if(handFile == NULL){
			WARN("Can't open file %s", filePath);
			continue;
		}

		if(	fread(header, sizeof(png_byte), PNGHEAD_SIZE, handFile) == PNGHEAD_SIZE
			&& png_sig_cmp(header, 0, PNGHEAD_SIZE) == 0
		){
			XTRA_LOG("File %s opened as PNG", filePath);

		}else{
			WARN("File %s isn't a PNG", filePath);
			fclose(handFile);
			continue;
		}

		++numTexs;
		(*dynarrTextures) = (sTex**)realloc_chk((*dynarrTextures), (numTexs+1) * sizeof(sTex*));
		(*dynarrTextures)[numTexs]=NULL;

		refTex = (*dynarrTextures)[numTexs-1] = (sTex*)malloc_chk(sizeof(sTex));
		memset(refTex, 0, sizeof(sTex));

		refTex->pngptrData = png_create_read_struct(
			PNG_LIBPNG_VER_STRING, NULL, NULL, &myPNGWarnFoo
		);

		if(refTex->pngptrData == NULL){
			WARN("Unable to create png struct");
			fclose(handFile);
			continue;
		}

		if(setjmp(png_jmpbuf(refTex->pngptrData)) != 0){ 	/** jumps here on errors. */
			cleanupPNGImg(
				refTex->pngptrData,
				&refTex->dynarrRows
			);
			png_destroy_read_struct(
				&(refTex->pngptrData),
				&(refTex->pngptrInfo),
				NULL
			);
			refTex->h = refTex->w = 0;

		}else{
			refTex->pngptrInfo = png_create_info_struct(
				refTex->pngptrData
			);

			if(refTex->pngptrInfo == NULL){
				WARN("Unable to create png info struct");
				fclose(handFile);
				continue;
			}

			/** setup PNG decode */
			png_init_io(refTex->pngptrData, handFile);
			png_set_sig_bytes(refTex->pngptrData, PNGHEAD_SIZE);
			png_read_info(refTex->pngptrData, refTex->pngptrInfo);

			png_byte colorCurrent = png_get_color_type(
				refTex->pngptrData, refTex->pngptrInfo
			);

			png_set_filler(refTex->pngptrData, 0, PNG_FILLER_AFTER);
			png_set_packing(refTex->pngptrData);	/** if < 8 bits */

			{
				png_color_8p sig_bit;
				if (png_get_sBIT(refTex->pngptrData, refTex->pngptrInfo, &sig_bit))
					png_set_shift(refTex->pngptrData, sig_bit);
			}

			switch(colorCurrent){
				case PNG_COLOR_TYPE_RGB_ALPHA:
					/** already good */
				break;
				case PNG_COLOR_TYPE_RGB:
					png_set_tRNS_to_alpha(refTex->pngptrData);
				break;
				case PNG_COLOR_TYPE_PALETTE:
					png_set_palette_to_rgb( refTex->pngptrData );
					png_set_tRNS_to_alpha(refTex->pngptrData);
				break;
				case PNG_COLOR_TYPE_GRAY:
					png_set_expand_gray_1_2_4_to_8( refTex->pngptrData );
					png_set_tRNS_to_alpha(refTex->pngptrData);
				break;
				default:
					WARN("unsupported colour");
				break;
			}

			png_read_update_info(refTex->pngptrData, refTex->pngptrInfo);

			colorCurrent = png_get_color_type(
				refTex->pngptrData, refTex->pngptrInfo
			);

			if(colorCurrent != PNG_COLOR_TYPE_RGB_ALPHA){
				printf("<warning> %s didn't convert to the right colour type\n", files->dynarrFiles[idxFile]);
				png_destroy_read_struct(&refTex->pngptrData, &refTex->pngptrInfo, (png_infopp)NULL);
				fclose(handFile);
				continue;
			}

			refTex->colorType = colorCurrent;

			const int numPasses = png_set_interlace_handling( refTex->pngptrData );

			/** setup other data */
			copyString(&refTex->name, files->dynarrFiles[idxFile]);

			/** setup texture */
			unsigned int row;
			const png_uint_32 sizeRow = png_get_rowbytes( refTex->pngptrData, refTex->pngptrInfo );

			refTex->w = png_get_image_width(
				refTex->pngptrData, refTex->pngptrInfo
			);
			refTex->h = png_get_image_height(
				refTex->pngptrData, refTex->pngptrInfo
			);

			if(sizeRow/refTex->w != DEFAULT_BYTE_PP){
				WARN("%s didn't convert to the right bit depth", refTex->name);
				png_destroy_read_struct(&refTex->pngptrData, &refTex->pngptrInfo, (png_infopp)NULL);
				fclose(handFile);
				continue;
			}

			refTex->dynarrRows = calloc_chk((refTex->h +1), sizeof(png_byte*));
			refTex->dynarrRows[refTex->h] = NULL;

			for(row = 0; row < refTex->h; ++row)
				refTex->dynarrRows[row] = png_malloc(refTex->pngptrData, sizeRow);

			unsigned int pass;
			for(pass=0; pass < numPasses; ++pass){
				for(row = 0; row < refTex->h; ++row){
					png_read_rows(
						refTex->pngptrData,
						&refTex->dynarrRows[row],
						NULL,
						1
					);
				}
			}

			png_read_end(refTex->pngptrData, refTex->pngptrInfo);
		}

		fclose(handFile);
	}
	return NOPROB;
}
Esempio n. 9
0
errCode arrangeTextures(
	sTex **arrTexs,
	sSeqList *pSeqs, 
	sStillList *pStills,
	sFontList *pFonts,
	sSheetList *pOutSheets,
	unsigned int maxSquare
){
	unsigned int curW, curH;
	int idxFit;
	bool makeSheet, freshSheet;
	unsigned int curSeq, curStill, curFrame, curFont;
	sTex *curTex;
	sSheet *curSheet;
	sTexSeq *refSeq;
	sSquare *refSqr;
	sFont *refFnt;
	unsigned int *dynarrSeqIdxs;
	unsigned int *dynarrPrevFrame;	/** If not -1, we're trying to split an animation over multiple sheets */ 
	unsigned int *dynarrStillIdxs;
	unsigned int *dynarrFontIdxs;
	
	if(pSeqs == NULL || pStills == NULL || pFonts == NULL)
		return ERROR;

	/** Arrays used to keep track of things that still need assigning */
	if(pSeqs->num > 0){
		dynarrSeqIdxs = calloc_chk(pSeqs->num, sizeof(unsigned int));
		dynarrPrevFrame = calloc_chk(pSeqs->num, sizeof(unsigned int));

		unsigned int i;
		for(i=0; i < pSeqs->num; ++i){
			dynarrSeqIdxs[i] = i;
			dynarrPrevFrame[i] = (unsigned int)-1;
		}
		
	}else{
		dynarrSeqIdxs = NULL;
		dynarrPrevFrame = NULL;
	}
	
	if(pStills->num > 0){
		dynarrStillIdxs = calloc_chk(pStills->num, sizeof(unsigned int));
		
		unsigned int i;
		for(i=0; i < pStills->num; ++i)
			dynarrStillIdxs[i] = i;
		
	}else{
		dynarrStillIdxs = NULL;
	}

	if(pFonts->num > 0){
		dynarrFontIdxs = calloc_chk(pFonts->num, sizeof(unsigned int));

		unsigned int i;
		for(i=0; i < pFonts->num; ++i)
			dynarrFontIdxs[i] = 0;
	}else{
		dynarrFontIdxs = NULL;
	}
	
	/** Main arrangement stuff */
	do{
		sListSquares holes;	memset(&holes, 0, sizeof(sListSquares));

		++pOutSheets->num;
		pOutSheets->dynarrSheets = realloc_chk(
			pOutSheets->dynarrSheets, 
			pOutSheets->num * sizeof(sSheet*)
		);
		curSheet = malloc_chk(sizeof(sSheet));
		memset(curSheet, 0, sizeof(sSheet));
		pOutSheets->dynarrSheets[ pOutSheets->num -1 ] = curSheet;
		
		makeSheet = FALSE;
		freshSheet = TRUE;
		curSeq =curStill =curFont =0; /** retry all the differed stills and sequences*/
		curW =curH =0;
	
		XTRA_LOG("Making sheet %i", (int)pOutSheets->num);
		
		while(makeSheet==FALSE && (dynarrSeqIdxs != NULL || dynarrStillIdxs != NULL || dynarrFontIdxs != NULL) ){
			const bool endOfSeqs = (curSeq < pSeqs->num) ? FALSE : TRUE;
			const bool endOfStills = (curStill < pStills->num) ? FALSE : TRUE;
			const bool endOfFonts = (curFont < pFonts->num) ? FALSE : TRUE;
			
			//consolidate(&holes); /** a bit broken */

			if(dynarrSeqIdxs != NULL && endOfSeqs == FALSE){ 
				if(dynarrSeqIdxs[curSeq] != (unsigned int)-1){
					refSeq = &(pSeqs->dynarrSeqs[ dynarrSeqIdxs[curSeq] ]);

					if(refSeq->num > 0){	/** See if the entire sequence can fit first. */
						{
							sListSquares tmpHoles;	memset(&tmpHoles, 0, sizeof(sListSquares));

							XTRA_LOG("Probing sheet");
							copySquares(&tmpHoles, &holes);

							if(dynarrPrevFrame[curSeq] != (unsigned int)-1)
								curFrame = dynarrPrevFrame[curSeq];
							else
								curFrame = 0;

							idxFit = (unsigned int)-1;
							while(curFrame < refSeq->num){
								curTex = arrTexs[ refSeq->dynarrTexIDs[curFrame] ];

								if(curTex->w > maxSquare || curTex->h > maxSquare){	/** We can't do much else here besides bomb out, because we can't mark the texture as a dud here. */
									ERROR_LOG("arrangeTextures: Texture %s is too large for the max texture size.", curTex->name);
									cleanupListSquares(&holes);
									cleanupListSquares(&tmpHoles);
									goto arrangeTextures_fail;
								}

								idxFit = fitNFillSquare(&tmpHoles, curTex->w, curTex->h, maxSquare, maxSquare);
								if(idxFit < 0)
									break;
							
								++curFrame;
							}

							cleanupListSquares(&tmpHoles);
							XTRA_LOG("Done with probe");
						}

						if(idxFit >= 0 || freshSheet == TRUE){
							refSeq->dynarrSheetIDs = calloc_chk(refSeq->num, sizeof(unsigned int));

							if(dynarrPrevFrame[curSeq] != (unsigned int)-1)
								curFrame = dynarrPrevFrame[curSeq];
							else
								curFrame = 0;

							while(curFrame < refSeq->num){
								curTex = arrTexs[ refSeq->dynarrTexIDs[curFrame] ];
								idxFit = fitNFillSquare(&holes, curTex->w, curTex->h, maxSquare, maxSquare);
								if(idxFit >= 0){
									refSqr = &(holes.dynarrSquares[idxFit]);
									refSeq->dynarrSheetIDs[curFrame] = (unsigned int)(pOutSheets->num -1);
									curTex->x = refSqr->x;
									curTex->y = refSqr->y;

									++curSheet->num;
									curSheet->dynarrTexIDs = realloc_chk(
										curSheet->dynarrTexIDs,
										curSheet->num *sizeof(unsigned int)
									);
									curSheet->dynarrTexIDs[curSheet->num -1] = refSeq->dynarrTexIDs[curFrame];
									freshSheet = FALSE;

								}else{	/** Try again on a fresh sheet. */
									dynarrPrevFrame[curSeq] = curFrame;
									break;
								}
								++curFrame;
							}
						}
					}else{
						curFrame = 0;
					}

					if(curFrame == refSeq->num)	/** success */
						dynarrPrevFrame[curSeq] = dynarrSeqIdxs[curSeq] = (unsigned int)-1;
				}
				++curSeq;
				
			
			}else if(dynarrStillIdxs != NULL && endOfStills == FALSE){
				if(dynarrStillIdxs[curStill] != (unsigned int)-1){
					curTex = arrTexs[ 
						pStills->dynarrTexIDs[
							dynarrStillIdxs[curStill]
						] 
					];
					
					if(pStills->dynarrSheetIDs == NULL)
						pStills->dynarrSheetIDs = calloc_chk(pStills->num, sizeof(unsigned int));
							
					if(curTex->w > maxSquare || curTex->h > maxSquare){	/** We can't do much else here besides bomb out, because we can't mark the texture as a dud here. */
						ERROR_LOG("arrangeTextures: Texture %s is too large for the max texture size.", curTex->name);
						cleanupListSquares(&holes);
						goto arrangeTextures_fail;
					}
				
					idxFit = fitNFillSquare(&holes, curTex->w, curTex->h, maxSquare, maxSquare);
					if(idxFit >= 0){
						refSqr = &(holes.dynarrSquares[idxFit]);
						curTex->x = refSqr->x;
						curTex->y = refSqr->y;
						pStills->dynarrSheetIDs[curStill] = (unsigned int)(pOutSheets->num -1);
						curSheet->dynarrTexIDs = realloc_chk(
							curSheet->dynarrTexIDs, 
							(curSheet->num +1) * sizeof(unsigned int)
						);
						curSheet->dynarrTexIDs[curSheet->num] = pStills->dynarrTexIDs[ dynarrStillIdxs[curStill] ];
						++curSheet->num;
						freshSheet = FALSE;

						dynarrStillIdxs[curStill] = (unsigned int)-1;

					}else if(freshSheet == TRUE){
						ERROR_LOG("Unable to fit still");
						goto arrangeTextures_fail;
					}

				}
				++curStill;

			}else if(dynarrFontIdxs != NULL && endOfFonts == FALSE){
				if(dynarrFontIdxs[curFont] != (unsigned int)-1){
					unsigned int idxGlyph;

					refFnt = pFonts->dynarrFonts[curFont];
					idxFit = (unsigned int)-1;

					{	/** probe sheet */
						sListSquares tmpHoles;	memset(&tmpHoles, 0, sizeof(sListSquares));

						XTRA_LOG("Probing sheet");
						copySquares(&tmpHoles, &holes);

						for(idxGlyph= dynarrFontIdxs[curFont]; idxGlyph < refFnt->num; ++idxGlyph){
							curTex = arrTexs[ refFnt->dynarrTexIDs[idxGlyph] ];
							idxFit = fitNFillSquare(&tmpHoles, curTex->w, curTex->h, maxSquare, maxSquare);
							if(idxFit < 0)
								break;
						}

						cleanupListSquares(&tmpHoles);
						XTRA_LOG("Done with probe");
					}

					if(idxFit >= 0 || freshSheet == TRUE){
						unsigned int i = dynarrFontIdxs[curFont];

						while(dynarrFontIdxs[curFont] < idxGlyph){
							curTex = arrTexs[
								refFnt->dynarrTexIDs[
									dynarrFontIdxs[curFont]
								]
							];
							idxFit = fitNFillSquare(&holes, curTex->w, curTex->h, maxSquare, maxSquare);
							if(idxFit < 0){
								ERROR_LOG("Unable to fit font, somehow?");
								goto arrangeTextures_fail;
							}

							refSqr = &(holes.dynarrSquares[idxFit]);
							curTex->x = refSqr->x;
							curTex->y = refSqr->y;
							++dynarrFontIdxs[curFont];
						}

						if(dynarrFontIdxs[curFont] -i > 0){
							unsigned int numPrev = curSheet->num;
							refFnt->dynarrSheetIDs = realloc_chk(
								refFnt->dynarrSheetIDs,
								dynarrFontIdxs[curFont] *sizeof(unsigned int)
							);

							unsigned int s;
							for(s=i; s < dynarrFontIdxs[curFont]; ++s)
								refFnt->dynarrSheetIDs[s] = (unsigned int)(pOutSheets->num -1);

							curSheet->num += dynarrFontIdxs[curFont] -i;
							curSheet->dynarrTexIDs = realloc_chk(
								curSheet->dynarrTexIDs,
								curSheet->num *sizeof(unsigned int)
							);
		
							memcpy(
								&curSheet->dynarrTexIDs[numPrev],
								&refFnt->dynarrTexIDs[i],
								(curSheet->num -numPrev) *sizeof(unsigned int)
							);
						}else{
							WARN("fonts not added to sheet");
						}

						if(dynarrFontIdxs[curFont] == refFnt->num)
							dynarrFontIdxs[curFont] = (unsigned int)-1;

						freshSheet = FALSE;
					}
				}
				++curFont;

			}else{	/** Check if we need to make another sheet, and cleanup any arrays that are finished. */

				if(dynarrSeqIdxs != NULL && endOfSeqs == TRUE){
					for(curSeq=0; curSeq < pSeqs->num; ++curSeq){
						if(dynarrSeqIdxs[curSeq] != (unsigned int)(-1))
							break;
					}

					if(curSeq == pSeqs->num){
						SAFE_DELETE(dynarrSeqIdxs);
						SAFE_DELETE(dynarrPrevFrame);
					}else{
						makeSheet = TRUE;
					}
				}

				if(dynarrFontIdxs != NULL && endOfFonts == TRUE){
					for(curFont=0; curFont < pFonts->num; ++curFont){
						if(dynarrFontIdxs[curFont] != (unsigned int)-1)
							break;
					}

					if(curFont == pFonts->num){
						SAFE_DELETE(dynarrFontIdxs);
					}else{
						makeSheet = TRUE;
					}
				}

				if(dynarrStillIdxs != NULL && endOfStills == TRUE){
					for(curStill=0; curStill < pStills->num; ++curStill){
						if(dynarrStillIdxs[curStill] != (unsigned int)(-1))
							break;
					}

					if(curStill == pStills->num){
						SAFE_DELETE(dynarrStillIdxs);
					}else{
						makeSheet = TRUE;
					}
				}
			}
			
			/** keep the sheet up to date. */
			curSheet->w = holes.boundryW;
			curSheet->h = holes.boundryH;
		}

		cleanupListSquares(&holes);
		
	}while(makeSheet==TRUE);
	
	if(dynarrStillIdxs != NULL || dynarrSeqIdxs != NULL){
		ERROR_LOG("Didn't cleanup memory");
		return ERROR;
	}
	
	return NOPROB;
	
arrangeTextures_fail:
	
	SAFE_DELETE(dynarrSeqIdxs);
	SAFE_DELETE(dynarrStillIdxs);
	SAFE_DELETE(dynarrPrevFrame);
	return ERROR;
}
Esempio n. 10
0
CMDLINE *linetok(const char *line)
{
    char *tokens, *p, *sepp;
    bool quoting = false;
    CMDLINE *cmdl = NULL;

    if(*line == '\0') {
        return NULL;
    }
    tokens = strdup_chk(line, "tokens");
    /* コメントを削除 */
    for(p = tokens; *p != '\0'; p++) {
        /* 「'」で囲まれた文字列の処理。「''」は無視 */
        if(*p == '\'' && *(p+1) != '\'' && !(p > tokens && *(p-1) == '\'')) {
            quoting = !quoting;
        } else if(quoting == false && *p == ';') {
            *p = '\0';
            break;
        }
    }
    if(*tokens != '\n' && *tokens != '\0') {
        p = tokens;
        cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
        cmdl->label = malloc_chk(LABELSIZE + 1, "cmdl.label");
        /* ラベルの取得。行の先頭が空白またはタブの場合、ラベルは空 */
        if((sepp = p + strcspn(p, " \t\n")) == p){
            *(cmdl->label) = '\0';
        } else {        /* ラベルを取得 */
            *sepp = '\0';
            /* 文字列が長すぎる場合はエラー */
            if(strlen(p) > LABELSIZE) {
                setcerr(104, p);    /* label length is too long */
            } else {
                strcpy(cmdl->label, p);
            }
            p = sepp + 1;
        }
        /* ラベルと命令の間の空白をスキップ */
        while(*p == ' ' || *p == '\t') {
            p++;
        }
        /* 命令とオペランドの取得 */
        if(*p == '\n' || *p == '\0') {        /* 命令がない場合は、終了 */
            if(*(cmdl->label) != '\0') {      /* ラベルが定義されていて命令がない場合はエラー */
                setcerr(105, "");    /* no command in the line */
            }
            FREE(cmdl->label);
            FREE(cmdl);
        } else {
            /* 命令の取得 */
            sepp = p + strcspn(p, " \t\n");
            *sepp = '\0';
            cmdl->cmd = strdup_chk(p, "cmdl.cmd");
            p = sepp + 1;
            /* 命令とオペランドの間の空白をスキップ */
            while(*p == ' ' || *p == '\t') {
                p++;
            }
            /* 改行かタブまでの文字列を取得 */
            /* 「'」で囲まれた文字列に含まれる場合があるため、空白は無視 */
            if((sepp = p + strcspn(p, "\t\n")) > p) {
                *sepp = '\0';
                cmdl->opd = opdtok(p);
            } else {
                cmdl->opd = malloc_chk(sizeof(OPD), "cmdl.opd");
                cmdl->opd->opdc = 0;
            }
        }
    }
    FREE(tokens);
    return cmdl;
}