錯(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()?);
}