File: tparse.h

package info (click to toggle)
viewcvs 0.9.2%2Bcvs.1.0.dev.2004.07.28-4.1etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 1,452 kB
  • ctags: 1,355
  • sloc: python: 10,100; cpp: 840; ansic: 763; yacc: 526; sh: 163; makefile: 115
file content (228 lines) | stat: -rw-r--r-- 5,568 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
# Copyright (C) 2000-2002 The ViewCVS Group. All Rights Reserved.
# This file has been rewritten in C++ from the rcsparse.py file by
# Lucas Bruand <lucas.bruand@ecl2002.ec-lyon.fr>
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
#   Greg Stein, PO Box 760, Palo Alto, CA, 94302
#   gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
# This software is being maintained as part of the ViewCVS project.
# Information is available at:
#    http://viewcvs.sourceforge.net/
#
# This file was originally based on portions of the blame.py script by
# Curt Hagenlocher.
#
# -----------------------------------------------------------------------
#
*/

/*
   This C++ library offers an API to a performance-oriented RCSFILE parser.
   It does little syntax checking.
 
   Version: $Id: tparse.h,v 1.7 2004/04/06 02:52:08 cmpilato Exp $
 */
#define CHUNK_SIZE 30000
#ifndef __PARSE_H
#define __PARSE_H
#include <iostream.h>
#include <strstream.h>
#include <stdio.h>
#include <fstream.h>
#include <string.h>
#include <stdlib.h>
#define delstr(a) if (a != NULL) { delete [] a; a=NULL; };

/* This class represents a exception that occured during the parsing
   of a file */
class RCSParseError
{
  public:
    char *value;
    RCSParseError() {};
    RCSParseError(char *myvalue)
    {
      value = myvalue;
    };
    char *getvalue()
    {
      return value;
    };
};

class RCSIllegalCharacter : public RCSParseError
{
  public:
    RCSIllegalCharacter(char *myvalue)
    {
      value = myvalue;
    };
};

class RCSExpected : public RCSParseError
{
  public:
    char *got;
    char *wanted;
    RCSExpected(char *mygot, char *mywanted)
    {
      got = mygot;
      wanted = mywanted;
    }
    char *getvalue()
    {
      ostrstream *out = new ostrstream();
      (*out) << "RCSExcepted: " << wanted << " Got: " << got << endl;
      out->put('\0');
      return out->str();
    };
};

/* This class is used to store a list of the branches of a revision */
class Branche
{
  public:
    char *name;
    Branche *next;
    Branche(char *myname, Branche *mynext)
    {
      name = myname;
      next = mynext;
    };
    ~Branche()
    {
      delstr(name);
      name = NULL;
      if (next != NULL)
        delete next;
      next = NULL;
    };
};

/* This class is a handler that receive the event generated by the parser
   i.e.: When we reach the head revision tag, etc... */
class Sink
{
  public:
    Sink() {};
    virtual int set_head_revision(char * revision) = 0;
    virtual int set_principal_branch(char *branch_name) = 0;
    virtual int define_tag(char *name, char *revision) = 0;
    virtual int set_comment(char *comment) = 0;
    virtual int set_description(char *description) = 0;
    virtual int define_revision(char *revision, long timestamp, 
                                char *author, char *state, 
                                Branche *branches, char *next) = 0;
    virtual int set_revision_info(char *revision, char *log, char *text) = 0;
    virtual int tree_completed() = 0;
    virtual int parse_completed() = 0;
};

/* The class is used to get one by one every token in the file. */
class TokenParser
{
  private:
    istream *input;
    char buf[CHUNK_SIZE];
    int buflength;
    int idx;
    char *backget;
  public:
    char *semicol;
    char *get();
    void unget(char *token);
    int eof()
    {
      return (input->gcount() == 0);
    };
    void matchsemicol()
    {
      char *ptr = get();
      if (ptr != semicol)
        throw RCSExpected(ptr, semicol);
    };
    void match(char *token)
    {
      char *ptr;
      if (strcmp(ptr = get(), token) != 0)
        throw RCSExpected(ptr, token);
      delstr( ptr);
    };
    TokenParser(istream *myinput)
    {
      input = myinput;
      backget = NULL;
      idx = 0;
      semicol = ";";
      input->read(buf, CHUNK_SIZE);
      if ( (buflength = input->gcount()) == 0 )
        throw RCSParseError("Non-existing file or empty file");
    };
    ~TokenParser()
    {
      if (input != NULL)
      {
        delete input;
        input = NULL;
      };
      if (backget != NULL)
      {
        delstr(backget);
        backget = NULL;
      };
    };
};

/* this is the class that does the actual job: by reading each part of
   the file and thus generate events to a sink event-handler*/
class tparseParser
{
  private:
    TokenParser *tokenstream;
    Sink *sink;
    int parse_rcs_admin();
    int parse_rcs_tree();
    int parse_rcs_description();
    int parse_rcs_deltatext();
  public:
    tparseParser(istream *myinput, Sink* mysink)
    {
      sink = mysink;
      tokenstream = new TokenParser(myinput);

      if (parse_rcs_admin())
        return;
      if (parse_rcs_tree())
        return;

      // many sinks want to know when the tree has been completed so they can
      // do some work to prepare for the arrival of the deltatext
      if (sink->tree_completed())
        return;

      if (parse_rcs_description())
        return;
      if (parse_rcs_deltatext())
        return;

      // easiest for us to tell the sink it is done, rather than worry about
      // higher level software doing it.
      if (sink->parse_completed())
        return;
    }
    ~tparseParser()
    {
      delete tokenstream;
      delete sink;
    }
};

#endif /* __PARSE_H */