錯(cuò)誤報(bào)告模塊作用:記錄并報(bào)告編譯過程中出現(xiàn)的錯(cuò)誤和警告
/*************************************************
?*???????????????????????????????????????????????*
?*??Module:?errors.c?????????????????????????????*
?*??Description:?????????????????????????????????*
?*??????Errors?reporting?module.?This?module?????*
?*??????collects?error/warning?messages?in?a?????*
?*??????list,?marking?them?with?the?line?number??*
?*??????on?which?they?occurred.?They?can?then????*
?*??????be?sorted?and?printed?as?a?batch.????????*
?*??Author:?Van?Oostenrijk,?A.C.?????????????????*
?*??Modifications:???????????????????????????????*
?*???????????????????????????????????????????????*
?*************************************************
?*???????????????????????????????????????????????*
?*???This?program?is?free?software;?you?can??????*
?*???redistribute?it?and/or?modify??it?under?????*
?*???the?terms?of?the?GNU?General?Public?????????*
?*???License?as?published?by?the?Free????????????*
?*???Software?Foundation;?either?version?2???????*
?*???of?the?License,?or?(at?your?option)?any?????*
?*???later?version.??????????????????????????????*
?*???????????????????????????????????????????????*
?*************************************************/
/*?printf,?NULL?*/
#include?<stdio.h>
/*?malloc,?free?*/
#include?<stdlib.h>
/*?assert?macro?*/
#include?<assert.h>
/*?General?macros.?*/
#include?"defs.h"
/*?Include?linked?list?interface.?*/
#include?"list.h"
//所有的錯(cuò)誤信息都記錄在一個(gè)鏈表中
/*************************************************
?*???????????????????????????????????????????????*
?*??MACROS???????????????????????????????????????*
?*???????????????????????????????????????????????*
?*************************************************/
/*
?*?Define?the?character?used?to?terminate?messages.?Can?be
?*?the?empty?string.
?*/
#define?MESSAGEDOT?"."
/*************************************************
?*???????????????????????????????????????????????*
?*??TYPES????????????????????????????????????????*
?*???????????????????????????????????????????????*
?*************************************************/
/*
?*??This?structure?holds?a?single?error/warning
?*??message?(a?string)?and?the?line?number?on?which
?*??it?occurred.
?*/
typedef?struct
{
????int?lineno;
????char?*text;
}?ReportEntry;
/*************************************************
?*???????????????????????????????????????????????*
?*??GLOBALS??????????????????????????????????????*
?*???????????????????????????????????????????????*
?*************************************************/
//錯(cuò)誤和警告計(jì)數(shù)器
static?int?numErrors?=?0,?numWarnings?=?0;
//指向記錄警告信息和錯(cuò)誤信息的鏈表表頭,?貌似以前有人說數(shù)據(jù)結(jié)構(gòu)沒有用的?
static?List?*report?=?NULL;
/*************************************************
?*???????????????????????????????????????????????*
?*??FUNCTION?DEFNIITIONS?????????????????????????*
?*???????????????????????????????????????????????*
?*************************************************/
/*
?*??Free?specified?instance?of?the?ReportEntry
?*??structure.?This?callback?function?is?used
?*??by?[report],?the?list?of?Report?Entries.
?*/
?//釋放鏈表中entry指向的節(jié)點(diǎn)
static?BOOL?DeleteReportEntry(?void?*entry?)
{
????free(?(?(ReportEntry?*)?entry)->text?);?//釋放text的空間
????free(?entry?);??//釋放ReportEntry結(jié)構(gòu)體的空間
????return(?TRUE?);
}
/*
?*?Add?a?ReportEntry?to?the?report,?with?the
?*?specified?[prefix]?("error"?or?"warning"),
?*?the?message?[message]?and?the?line?number
?*?[lineno].?Include?the?character?position
?*?[charpos]?if?it?is?not?-1.
?*/
?//在鏈表尾部增加一條節(jié)點(diǎn),用于記錄警告或者錯(cuò)誤信息
static?void?AddText(?char?*prefix,?char?*message,?int?lineno,?int?charpos?)
{
????ReportEntry?*entry;
????assert(?prefix?!=?NULL?);
????assert(?message?!=?NULL?);
????entry?=?(ReportEntry*)?malloc(?sizeof(?ReportEntry?)?);
????//多分配了40個(gè)字節(jié)用于記錄錯(cuò)誤或者警告的行號(hào)和列號(hào),?"error"?"warning"前綴和點(diǎn)等
????entry->text?=?(char*)?malloc(?strlen(message)?+?40?);
????if(?charpos?==?-1?)?//如果到了文件尾部,沒有出錯(cuò)的charpos
????{
????????sprintf(?entry->text,?"%d?-?%s:?%s%s",?lineno,?prefix,
????????????message,?MESSAGEDOT?);
????????/*?DEBUG(?"%d?-?%s:?%s%s\n",?lineno,?prefix,
????????????message,?MESSAGEDOT?);?*/
????}
????else
????{
????????sprintf(?entry->text,?"%d:%d?-?%s:?%s%s",?lineno,
????????????charpos,?prefix,?message,?MESSAGEDOT?);
????????/*?DEBUG(?"%d:%d?-?%s:?%s%s\n",?lineno,
????????????charpos,?prefix,?message,?MESSAGEDOT?);?*/
????}
????entry->lineno?=?lineno;
????ListAppend(?report,?entry?);????//添加到鏈表尾部
}
//添加錯(cuò)誤信息,包括列號(hào)
void?AddPosError(?char?*message,?int?lineno,?int?charpos?)
{
????numErrors++;
????AddText(?"error",?message,?lineno,?charpos?);
}
//添加錯(cuò)誤信息,不包括列號(hào)
void?AddError(?char?*message,?int?lineno?)
{
????numErrors++;
????AddText(?"error",?message,?lineno,?-1?);
}
//添加警告信息,包括列號(hào)
void?AddPosWarning(?char?*message,?int?lineno,?int?charpos?)
{
????numWarnings++;
????AddText(?"warning",?message,?lineno,?charpos?);
}
//添加警告信息,不包括列號(hào)
void?AddWarning(?char?*message,?int?lineno?)
{
????numWarnings++;
????AddText(?"warning",?message,?lineno,?-1?);
}
//返回錯(cuò)誤總數(shù)
int?GetErrorCount()
{
????return(?numErrors?);
}
//返回警告總數(shù)
int?GetWarningCount()
{
????return(?numWarnings?);
}
//初始化鏈表
void?InitializeReport()
{
????numErrors?=?0;
????numWarnings?=?0;
????if(?report?!=?NULL?)????//鏈表非空
????{
????????ListPurge(?report,?DeleteReportEntry?);
????}
????report?=?ListInit(?DeleteReportEntry?);?//注冊(cè)DeleteReportEntry為釋放節(jié)點(diǎn)空間的函數(shù)
}
//將一個(gè)無序(對(duì)行號(hào)而言)的鏈表刪除,并以該鏈表中的節(jié)點(diǎn)重新建立一個(gè)有序的鏈表
void?PrintReport()
{
????List?*sortedReport;
????int?lowestLine;
????int?targetEntry;
????int?i,?lineno;
????void?*entry;
????ListNode?*node;
????sortedReport?=?ListInit(?DeleteReportEntry?);
????/*
?????*?Remove?entries?from?report?and?put?them
?????*?in?sortedReport?(sorted).
?????*/
????while(?ListSize(?report?)?>?0?)?//report鏈表還不為空
????{
????????lowestLine?=?1?<<?30;???//錯(cuò)誤或警告信息的最小的行號(hào)
????????targetEntry?=?-1;???//最小的行號(hào)在鏈表中的index
????????/*?Find?lowest?line?number?*/
????????ListFirst(?report?);
????????for(?i?=?0;?i?<?ListSize(?report?);?i++?)
????????{
????????????lineno?=?(?(?ReportEntry*?)?ListGet(?report?)?)->lineno;
????????????if(?lineno?<?lowestLine?)
????????????{
????????????????targetEntry?=?i;
????????????????lowestLine?=?lineno;
????????????}
????????????ListNext(?report?);?//指向下一個(gè)節(jié)點(diǎn)
????????}
????????/*?Go?to?lowest?entry.?*/
????????ListFirst(?report?);
????????for(?i?=?0;?i?<?targetEntry;?i++?)
????????{
????????????ListNext(?report?);
????????}
????????/*?Remove?entry?from?report,?add?to?sortedReport?*/
????????entry?=?ListGet(?report?);
????????ListUnlink(?report?);
????????ListAppend(?sortedReport,?entry?);??//添加到有序鏈表中
????}
????ListPurge(?report,?DeleteReportEntry?);
????/*?Print?sortedReport.?*/
????node?=?ListFirstEx(?sortedReport?);?//獲取指向第一個(gè)節(jié)點(diǎn)的指針
????while(?node?!=?NULL?)
????{???//報(bào)告錯(cuò)誤或警告信息
????????fprintf(?stderr,?"%s\n",?((ReportEntry*)node->data)->text?);
????????node?=?ListNextEx(?node?);??//下一個(gè)節(jié)點(diǎn)
????}
????/*?Throw?away?list?and?contents.?*/
????//不需要該有序鏈表了,刪除之
????ListPurge(?sortedReport,?DeleteReportEntry?);
????//輸出錯(cuò)誤總數(shù)和警告總數(shù)
????fprintf(?stdout,?"%d?errors,?%d?warnings.\n",?GetErrorCount(),?GetWarningCount()?);
}