📄 uclmain.pas
字号:
{$IFNDEF LINUX}
{Console Event Handler. Will signal the pressing of Control-C to the progress
showing object to enable a controlled abortion of the process.
~param CtrlType the abort signal command being triggered
~result whether the signal has been handled and/or should be ignored }
function ConProc(CtrlType: DWORD): BOOL; stdcall;
begin
Result := CtrlType = CTRL_C_EVENT; //only intercept Ctrl-C
if Result then //was Ctrl-C?
Progress.CtrlCPressed; //forward this signal
end;
{$ENDIF}
{Parses the pascal data.
~result if the data could be parsed correctly }
function Parse: Boolean;
begin
Result := False; //assume it fails
State.StartParsing(False); //begin the parsing
try
try
Result := State.DoParsing; //parse all pascal files
except
on E: EParseException do //in case of errors
begin
WriteLn('***************************************************************');
//write position, kind and message of the error
WriteLn('Error while parsing: Kind: Row:Col:File');
WriteLn(ExceptTypeName[E.ExceptType], ': ',
E.ErrorPosition.Row, ':', E.ErrorPosition.Column, ':',
E.TheFile.InternalFileName);
WriteLn(E.Message);
WriteLn('***************************************************************');
end;
else
raise; //unknown/system error? => handle
end;
finally
State.FinishParsing; //finish the parsing
end;
end;
{Prints the messages that have been generated while parsing. }
procedure PrintParsingMessages;
var i :Integer; //counter through all files
begin
//write all messages
for i := 0 to State.ParserMessages.Count - 1 do //for each message
with State.ParserMessages[i] do
begin
if MessageType <> etNone then //show type of message
Write(ExceptTypeName[MessageType], ': ');
if MessageKind = pmkError then //and its kind
Write('ERROR: ')
else
if MessageKind = pmkHint then
Write('Hint: ');
//show position of the message
assert(assigned(EffectiveFile) = assigned(TheFile));
if assigned(EffectiveFile) then
Write(EffectiveFile.InternalFileName, ': ', EffectiveErrorPosition.Row,
':', EffectiveErrorPosition.Column, ': ');
WriteLn(Message); //show the messages
end;
if State.ParserMessages.Count <> 0 then //some messages available?
WriteLn; //print a separating line
end;
{Prints all unknown identifiers and types. }
procedure PrintUnknownIdentifiers;
var i :Integer; //counter through all files
PFile :TPascalFile; //file parser
j :Integer; //counter through all unknown identifiers
Position :TPosition; //position inside the file
begin
WriteLn('Unknown Idents (Row:Column) and Types:');
for i := 0 to State.FileList.Count - 1 do //for each file
begin
PFile := State.FileList[i]; //get it
if ((PFile.UnknownIdents.Count <> 0) or //has some unknown identifiers?
(PFile.UnknownTypeIdents.Count <> 0)) then
begin
WriteLn('*----- ', PFile.InternalFileName, ':');
for j := 0 to PFile.UnknownIdents.Count - 1 do //for each unknown
begin
Position.Row := Cardinal(PFile.UnknownIdents.Objects[j]) and
$003FFFFF;
Position.Column := Cardinal(PFile.UnknownIdents.Objects[j]) shr 22;
//write unknown identifier and its position
WriteLn(PFile.UnknownIdents[j],
' (', Position.Row, ':', Position.Column, ')');
end;
WriteLn(PFile.UnknownTypeIdents.Text); //write all unknown types
WriteLn(''); //and an empty line as separator
end; //if has some unknown identifiers
end; //for all files
end;
{Prints all messages generated while generating documentation. }
procedure PrintGenerationMessages;
var i :Integer; //counter through all messages
HasPos :Boolean; //if position of the message is known
begin
for i := 0 to State.GenerationMessages.Count - 1 do //for each message
with State.GenerationMessages[i], //get message
State.GenerationMessageDescriptions[MessageID], //and its descriptions
Descriptions[MessageNumber] do //with details
if not Filter.IsFiltered[Title, MessageNumber] then
begin
Write(MessageSeriousnesses[Seriousness], ': ', //general data
Title, ':', MessageNumber, ': ');
HasPos := True; //assume it has a position
if assigned(Position.Identifier) then //at an identifier?
begin
Write(Position.Identifier.InFile.InternalFileName, '.');
if assigned(Position.Identifier.MemberOf) then
Write(Position.Identifier.MemberOf.Name, '.');
Write(Position.Identifier.Name);
end
else
if assigned(Position.TheFile) then //for a file?
begin
Write(Position.TheFile.InternalFileName);
if Position.Position.Row > 0 then
Write(':', Position.Position.Row, ':', Position.Position.Column)
end
else //for user documentation?
if (Position.UserDocPage <> '') or (Position.UserDocFile <> '') then
Write('~[userDoc ', Position.UserDocPage, '.',
ExtractFileName(Position.UserDocFile))
else //for GUI help?
if (Position.GUIPageFile <> '') or (Position.GUIPageTopic <> '') then
Write('~gui ', Position.GUIPageFile, '#', Position.GUIPageTopic)
else
HasPos := False; //no position
if HasPos then //position written?
Write(': '); //write delimiter
WriteLn(Message); //write the message itself
end;
end;
{Handles the program parameters.
~param SkipFirstParam whether the first parameter of the program should be
skipped/ignored }
procedure HandleParameters(SkipFirstParam: Boolean);
begin
Parameters := TCLParameterOptions.Create; //create list for parameters
try
//first parameter should be skipped?
if SkipFirstParam and (Parameters.Parameters.Count <> 0) then
Parameters.Parameters.Delete(0); //delete it
Parameters.JADDState := State; //set state of the program
Parameters.SupportsStdInput := True; //allow parsing of Input
Parameters.Filter := Filter; //set filter of messages
if Parameters.HandleAllParameters then //and handle parameters
//when there was no explicit parameter to generate documentation, do it now
Parameters.CheckAutoGeneration;
finally
Parameters.Free; //free list of parameters
end;
end;
{Handles the parameters by parsing the pascal data and generating
documentation.
~param SkipFirstParam whether the first parameter of the program should be
skipped/ignored
~result if all parameters could be handled successfully }
function Main(SkipFirstParam: Boolean): Boolean;
var Ini :TIniFile; //default ini file of the program
//to load the current language texts
EditTexts :TDocumentationTextOptionWrapper;
begin
Result := True; //no errors so far
{$IFDEF LINUX}
SysUtils.DeferUserInterrupts := True; //intercept Ctrl-C
HookSignal(RTL_SIGINT);
// HookSignal(RTL_SIGQUIT);
{$ELSE}
SetConsoleCtrlHandler(@ConProc, True); //intercept Ctrl-C
{$ENDIF}
//create state
State := TJADDState.Create(ExtractFilePath(ParamStr(0)) + DefaultINIFile);
try
//open default ini file of the program
Ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + DefaultINIFile);
try
//load the language strings from the default ini file
EditTexts := TDocumentationTextOptionWrapper.Create;
try
EditTexts.LoadIniOptions(Ini);
finally
EditTexts.Free;
end;
State.ReadIni(Ini); //load state of the program
if not State.Generate.GeneratorAvailable then
//select default generator
if GeneratorClasses.IndexOf('TICHTMLDoc') <> -1 then
State.Generate.ChangeGeneratorByName('TICHTMLDoc')
else
State.Generate.ChangeGeneratorByName(GeneratorClasses[0]);
if (State.Generate.ExtractorClassName = '') and //no extractor set but
(ExtractorClasses.Count <> 0) then //extractors available?
//use any extractor of comments
State.Generate.ChangeExtractorByName(ExtractorClasses[0]);
if (State.Generate.EvaluatorClassName = '') and //no evaluator set but
(EvaluatorClasses.Count <> 0) then //evaluators available?
//use any evaluator of texts
State.Generate.ChangeEvaluatorByName(EvaluatorClasses[0]);
//create object to observe Ctrl-C
Progress := TVerboseCommandLineProgress.Create;
State.Progress := Progress;
ShowProgress := True;
Filter := TMessageFilter.Create; //create filter on messages
try
HandleParameters(SkipFirstParam); //now handle the parameters
finally
Filter.Free; //free the filter
end;
finally
Ini.Free; //close default ini file of the program
end;
finally
State.Free; //free the state
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -