| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 | {    FPDoc  -  Free Pascal Documentation Tool    Copyright (C) 2000 - 2003 by      Areca Systems GmbH / Sebastian Guenther, [email protected]    * Skeleton XML description file generator    See the file COPYING, included in this distribution,    for details about the copyright.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.}program MakeSkel;uses  SysUtils, Classes, Gettext,  dGlobals, PasTree, PParser,PScanner;resourcestring  STitle = 'MakeSkel - FPDoc skeleton XML description file generator';  SVersion = 'Version %s [%s]';  SCopyright = '(c) 2000 - 2003 Areca Systems GmbH / Sebastian Guenther, [email protected]';  SCmdLineHelp = 'See documentation for usage.';  SCmdLineInvalidOption = 'Ignoring unknown option "%s"';  SNoPackageNameProvided = 'Please specify a package name with --package=<name>';  SOutputMustNotBeDescr = 'Output file must be different from description filenames.';  SDone = 'Done.';type  TCmdLineAction = (actionHelp, actionConvert);  TSkelEngine = class(TFPDocEngine)  public    function CreateElement(AClass: TPTreeElement; const AName: String;      AParent: TPasElement; AVisibility :TPasMemberVisibility;      const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement; override;  end;const  CmdLineAction: TCmdLineAction = actionConvert;  OSTarget: String = {$I %FPCTARGETOS%};  CPUTarget: String = {$I %FPCTARGETCPU%};  FPCVersion: String = {$I %FPCVERSION%};  FPCDate: String = {$I %FPCDATE%};var  EmittedList,InputFiles, DescrFiles: TStringList;  DocLang: String;  Engine: TSkelEngine;  UpdateMode,  DisableErrors,  DisableSeealso,  DisableArguments,  DisableProtected,  DisablePrivate,  DisableFunctionResults: Boolean;  EmitClassSeparator: Boolean;  PackageName, OutputName: String;  f: Text;function TSkelEngine.CreateElement(AClass: TPTreeElement; const AName: String;  AParent: TPasElement; AVisibility : TPasMemberVisibility;  const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;  Function WriteThisNode(APasElement : TPasElement)  : Boolean;  Var    ParentVisible:Boolean;    PT,PP : TPasElement;  begin    ParentVisible:=True;    If (APasElement is TPasArgument) or (APasElement is TPasResultElement) then      begin      PT:=AParent;      // Skip ProcedureType or PasFunctionType      If (PT<>Nil) then        begin        if (PT is TPasProcedureType) or (PT is TPasFunctionType) then          PT:=PT.Parent;        If (PT<>Nil) and ((PT is TPasProcedure) or (PT is TPasProcedure))   then          PP:=PT.Parent        else          PP:=Nil;        If (PP<>Nil) and (PP is TPasClassType) then          begin          ParentVisible:=((not DisablePrivate or (PT.Visibility<>visPrivate)) and                         (not DisableProtected or (PT.Visibility<>visProtected)));          end;        end;      end;    Result:=Assigned(AParent) and (Length(AName) > 0) and            (ParentVisible and (not DisableArguments or (APasElement.ClassType <> TPasArgument))) and            (ParentVisible and (not DisableFunctionResults or (APasElement.ClassType <> TPasResultElement))) and            (not DisablePrivate or (AVisibility<>visPrivate)) and            (not DisableProtected or (AVisibility<>visProtected)) and            (Not Assigned(EmittedList) or (EmittedList.IndexOf(APasElement.FullName)=-1));    If Result and updateMode then      begin      Result:=FindDocNode(APasElement)=Nil;      If Result then        Writeln(stderr,'Creating documentation for new node ',APasElement.PathName);      end;  end;  Function WriteOnlyShort(APasElement : TPasElement) : Boolean;  begin    Result:=(APasElement.ClassType=TPasArgument) or            (APasElement.ClassType=TPasResultElement) or            (APasElement.ClassType=TPasEnumValue);  end;  Function IsTypeVarConst(APasElement : TPasElement) : Boolean;  begin    With APasElement do      Result:=(InheritsFrom(TPasType) and not InheritsFrom(TPasClassType)) or              (InheritsFrom(TPasResString)) or              (InheritsFrom(TPasVariable));  end;begin  Result := AClass.Create(AName, AParent);  Result.Visibility:=AVisibility;  if AClass.InheritsFrom(TPasModule) then    CurModule := TPasModule(Result);  if Result.ClassType = TPasModule then    begin    WriteLn(f);    WriteLn(f, '<!--');    WriteLn(f, '  ====================================================================');    WriteLn(f, '    ', Result.Name);    WriteLn(f, '  ====================================================================');    WriteLn(f, '-->');    WriteLn(f);    WriteLn(f, '<module name="', Result.Name, '">');    if not UpdateMode then      begin      WriteLn(f, '<short></short>');      WriteLn(f, '<descr>');      WriteLn(f, '</descr>');      end;    end  else if WriteThisNode(Result) then    begin    EmittedList.Add(Result.FullName); // So we don't emit again.    WriteLn(f);    if EmitClassSeparator and (Result.ClassType = TPasClassType) then      begin      WriteLn(f, '<!--');      WriteLn(f, '  ********************************************************************');      WriteLn(f, '    ', Result.PathName);      WriteLn(f, '  ********************************************************************');      WriteLn(f, '-->');      WriteLn(f);      end;    Writeln(F,'<!-- ', Result.ElementTypeName,' Visibility: ',VisibilityNames[AVisibility], ' -->');    WriteLn(f,'<element name="', Result.FullName, '">');    WriteLn(f, '<short></short>');    if Not WriteOnlyShort(Result) then      begin      WriteLn(f, '<descr>');      WriteLn(f, '</descr>');      if not (DisableErrors or IsTypeVarConst(Result)) then        begin        WriteLn(f, '<errors>');        WriteLn(f, '</errors>');        end;      if not DisableSeealso then        begin        WriteLn(f, '<seealso>');        WriteLn(f, '</seealso>');        end;      end;    WriteLn(f, '</element>');    end;end;procedure InitOptions;begin  InputFiles := TStringList.Create;  DescrFiles := TStringList.Create;  EmittedList:=TStringList.Create;  EmittedList.Sorted:=True;end;procedure FreeOptions;begin  DescrFiles.Free;  InputFiles.Free;end;Procedure Usage;begin  Writeln('Usage : ',ExtractFileName(Paramstr(0)),' [options]');  Writeln('Where [options] is one or more of :');  Writeln(' --descr=filename    Filename for update.');  Writeln(' --disable-arguments Do not create nodes for function arguments.');  Writeln(' --disable-errors    Do not create errors node.');  Writeln(' --disable-function-results');  Writeln('                     Do not create nodes for function arguments.');  Writeln(' --disable-private   Do not create nodes for class private fields.');  Writeln(' --disable-protected Do not create nodes for class protected fields.');  Writeln(' --disable-seealso   Do not create seealso node.');  Writeln(' --emit-class-separator');  Writeln('                     Emit descriptive comment between classes.');  Writeln(' --help              Emit help.');  Writeln(' --input=cmdline     Input file to create skeleton for.');  Writeln('                     Use options are as for compiler.');  Writeln(' --lang=language     Use selected language.');  Writeln(' --output=filename   Send output to file.');  Writeln(' --package=name      Specify package name (mandatory).');  Writeln(' --update            Update mode. Output only missing nodes.');end;procedure ParseOption(const s: String);  procedure AddToFileList(List: TStringList; const FileName: String);  var    f: Text;    s: String;  begin    if Copy(FileName, 1, 1) = '@' then    begin      Assign(f, Copy(FileName, 2, Length(FileName)));      Reset(f);      while not EOF(f) do      begin        ReadLn(f, s);        List.Add(s);      end;      Close(f);    end else      List.Add(FileName);  end;var  i: Integer;  Cmd, Arg: String;begin  if (s = '-h') or (s = '--help') then    CmdLineAction := actionHelp  else if s = '--update' then    UpdateMode := True  else if s = '--disable-arguments' then    DisableArguments := True  else if s = '--disable-errors' then    DisableErrors := True  else if s = '--disable-function-results' then    DisableFunctionResults := True  else if s = '--disable-seealso' then    DisableSeealso := True  else if s = '--disable-private' then    DisablePrivate := True  else if s = '--disable-protected' then    begin    DisableProtected := True;    DisablePrivate :=True;    end  else if (s = '--emitclassseparator') or (s='--emit-class-separator') then    EmitClassSeparator := True  else  begin    i := Pos('=', s);    if i > 0 then    begin      Cmd := Copy(s, 1, i - 1);      Arg := Copy(s, i + 1, Length(s));    end else    begin      Cmd := s;      SetLength(Arg, 0);    end;    if (Cmd = '-i') or (Cmd = '--input') then      AddToFileList(InputFiles, Arg)    else if (Cmd = '-l') or (Cmd = '--lang') then      DocLang := Arg    else if (Cmd = '-o') or (Cmd = '--output') then      OutputName := Arg    else if Cmd = '--package' then      PackageName := Arg    else if Cmd = '--descr' then      begin      if FileExists(Arg) then        DescrFiles.Add(Arg);      end    else      WriteLn(StdErr, Format(SCmdLineInvalidOption, [s]));  end;end;procedure ParseCommandLine;Const{$IFDEF Unix}  MoFileTemplate = '/usr/local/share/locale/%s/LC_MESSAGES/makeskel.mo';{$ELSE}  MoFileTemplate ='intl/makeskel.%s.mo';{$ENDIF}var  MOFilename: string;  i: Integer;begin  DocLang:='';  for i := 1 to ParamCount do    ParseOption(ParamStr(i));  If (DocLang<>'') then    begin    MOFilename:=Format(MOFileTemplate,[DocLang]);    if FileExists(MOFilename) then      gettext.TranslateResourceStrings(MoFileName)    else      writeln('NOTE: unable to find tranlation file ',MOFilename);    // Translate internal documentation strings    TranslateDocStrings(DocLang);    end;end;var  i,j: Integer;  Module: TPasModule;begin  InitOptions;  ParseCommandLine;  WriteLn(STitle);  WriteLn(Format(SVersion, [FPCVersion, FPCDate]));  WriteLn(SCopyright);  WriteLn;  if CmdLineAction = actionHelp then    Usage  else    begin    // Action is to create the XML skeleton    if Length(PackageName) = 0 then      begin      WriteLn(SNoPackageNameProvided);      Halt(2);      end;    if DescrFiles.IndexOf(OutputName)<>-1 then      begin      Writeln(SOutputMustNotBeDescr);      Halt(3)      end;    Assign(f, OutputName);    Rewrite(f);    WriteLn(f, '<?xml version="1.0" encoding="ISO-8859-1"?>');    WriteLn(f, '<fpdoc-descriptions>');    WriteLn(f, '<package name="', PackageName, '">');    // Process all source files    for i := 0 to InputFiles.Count - 1 do    begin      Engine := TSkelEngine.Create;      try       try         Engine.SetPackageName(PackageName);         if UpdateMode then           For J:=0 to DescrFiles.Count-1 do             Engine.AddDocFile(DescrFiles[J]);         Module := ParseSource(Engine, InputFiles[i], OSTarget, CPUTarget);         WriteLn(f, '');         WriteLn(f, '</module> <!-- ', Module.Name, ' -->');         WriteLn(f, '');       except         on e:EFileNotFoundError do           begin             Writeln(StdErr,' file ', e.message, ' not found');             close(f);             Halt(1);           end;         on e:EParserError do           begin             Writeln(StdErr,'', e.filename,'(',e.row,',',e.column,') Fatal: ',e.message);             close(f);             Halt(1);           end;       end;      finally        Engine.Free;       end;    end;    WriteLn(f, '</package>');    WriteLn(f, '</fpdoc-descriptions>');    Close(f);    WriteLn(SDone);    end;  FreeOptions;end.
 |