p4ruby 2014.2.0.pre3-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
data/ext/P4/p4result.h ADDED
@@ -0,0 +1,86 @@
1
+ /*******************************************************************************
2
+
3
+ Copyright (c) 2001-2008, Perforce Software, Inc. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ *******************************************************************************/
27
+
28
+ /*******************************************************************************
29
+ * Name : p4result.h
30
+ *
31
+ * Author : Tony Smith <tony@perforce.com> or <tony@smee.org>
32
+ *
33
+ * Description : C++ class for holding results of Perforce commands
34
+ *
35
+ ******************************************************************************/
36
+
37
+ class P4Result
38
+ {
39
+ public:
40
+
41
+ P4Result();
42
+
43
+ // Setting
44
+ void AddOutput( VALUE v );
45
+ void AddMessage( Error *e );
46
+ void AddTrack( const char *msg );
47
+ void AddTrack( VALUE t );
48
+ void DeleteTrack();
49
+
50
+ // Getting
51
+ VALUE GetOutput() { return output; }
52
+ VALUE GetErrors() { return errors; }
53
+ VALUE GetWarnings() { return warnings; }
54
+ VALUE GetMessages() { return messages; }
55
+ VALUE GetTrack() { return track; }
56
+
57
+ // Get errors/warnings as a formatted string
58
+ void FmtErrors( StrBuf &buf );
59
+ void FmtWarnings( StrBuf &buf );
60
+
61
+ // Set API level for backwards compatibility
62
+ void SetApiLevel( int l ) { apiLevel = l; }
63
+ // Testing
64
+ int ErrorCount();
65
+ int WarningCount();
66
+
67
+ // Clear previous results
68
+ void Reset();
69
+
70
+ // Ruby garbage collection
71
+ void GCMark();
72
+
73
+ private:
74
+ int Length( VALUE ary );
75
+ void Fmt( const char *label, VALUE ary, StrBuf &buf );
76
+ VALUE FmtMessage( Error *e );
77
+ VALUE WrapMessage( Error *e );
78
+
79
+ VALUE cP4Msg;
80
+ VALUE output;
81
+ VALUE warnings;
82
+ VALUE errors;
83
+ VALUE messages;
84
+ VALUE track;
85
+ int apiLevel;
86
+ };
@@ -0,0 +1,45 @@
1
+ /*******************************************************************************
2
+
3
+ Copyright (c) 2001-2008, Perforce Software, Inc. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ *******************************************************************************/
27
+
28
+ /*******************************************************************************
29
+ * Name : p4rubydebug.h
30
+ *
31
+ * Author : Tony Smith <tony@perforce.com> or <tony@smee.org>
32
+ *
33
+ * Description : Debugging support for P4Ruby
34
+ *
35
+ ******************************************************************************/
36
+ #ifndef P4RUBYDEBUG_H
37
+ # define P4RUBYDEBUG_H
38
+
39
+ #define P4RDB_COMMANDS ( debug > 0 )
40
+ #define P4RDB_CALLS ( debug > 1 )
41
+ #define P4RDB_DATA ( debug > 2 )
42
+ #define P4RDB_GC ( debug > 3 )
43
+ #define P4RDB_RPC ( debug > 8 )
44
+
45
+ #endif
@@ -0,0 +1,108 @@
1
+ /*******************************************************************************
2
+
3
+ Copyright (c) 2009, Perforce Software, Inc. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ *******************************************************************************/
27
+
28
+ /*******************************************************************************
29
+ * Name : p4specdata.cpp
30
+ *
31
+ * Author : Tony Smith <tony@perforce.com> or <tony@smee.org>
32
+ *
33
+ * Description : Ruby bindings for the Perforce API. SpecData subclass for
34
+ * P4Ruby. This class allows for manipulation of Spec data
35
+ * stored in a Ruby hash using the standard Perforce classes
36
+ *
37
+ ******************************************************************************/
38
+
39
+ #include <ruby.h>
40
+ #include "undefdups.h"
41
+ #include <p4/clientapi.h>
42
+ #include <p4/i18napi.h>
43
+ #include <p4/spec.h>
44
+ #include <p4/debug.h>
45
+ #include "p4rubydebug.h"
46
+ #include "p4utils.h"
47
+ #include "p4specdata.h"
48
+
49
+ StrPtr *
50
+ SpecDataRuby::GetLine( SpecElem *sd, int x, const char **cmt )
51
+ {
52
+ *cmt = 0;
53
+ VALUE val;
54
+ VALUE key;
55
+ StrBuf t;
56
+
57
+ key = P4Utils::ruby_string( sd->tag.Text(), sd->tag.Length() );
58
+ val = rb_hash_aref( hash, key );
59
+ if( val == Qnil ) return 0;
60
+
61
+ if( !sd->IsList() )
62
+ {
63
+ last = StringValuePtr( val );
64
+ return &last;
65
+ }
66
+
67
+ // It's a list, which means we should have an array value here
68
+
69
+ if( !rb_obj_is_kind_of( val, rb_cArray ) )
70
+ {
71
+ rb_warn( "%s should be an array element. Ignoring...",
72
+ sd->tag.Text() );
73
+ return 0;
74
+ }
75
+ val = rb_ary_entry( val, x );
76
+ if( val == Qnil ) return 0;
77
+
78
+ last = StringValuePtr( val );
79
+ return &last;
80
+ }
81
+
82
+ void
83
+ SpecDataRuby::SetLine( SpecElem *sd, int x, const StrPtr *v, Error *e )
84
+ {
85
+ VALUE key;
86
+ VALUE val;
87
+ VALUE ary;
88
+ StrBuf t;
89
+
90
+ key = P4Utils::ruby_string( sd->tag.Text(), sd->tag.Length() );
91
+ val = P4Utils::ruby_string( v->Text(), v->Length() );
92
+
93
+ if( sd->IsList() )
94
+ {
95
+ ary = rb_hash_aref( hash, key );
96
+ if( ary == Qnil )
97
+ {
98
+ ary = rb_ary_new();
99
+ rb_hash_aset( hash, key, ary );
100
+ }
101
+ rb_ary_store( ary, x, val );
102
+ }
103
+ else
104
+ {
105
+ rb_hash_aset( hash, key, val );
106
+ }
107
+ return;
108
+ }
@@ -0,0 +1,52 @@
1
+ /*******************************************************************************
2
+
3
+ Copyright (c) 2009, Perforce Software, Inc. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ *******************************************************************************/
27
+
28
+ /*******************************************************************************
29
+ * Name : p4specdata.h
30
+ *
31
+ * Author : Tony Smith <tony@perforce.com> or <tony@smee.org>
32
+ *
33
+ * Description : Ruby bindings for the Perforce API. SpecData subclass for
34
+ * P4Ruby. This class allows for manipulation of Spec data
35
+ * stored in a Ruby hash using the standard Perforce classes
36
+ *
37
+ ******************************************************************************/
38
+
39
+ class SpecDataRuby : public SpecData
40
+ {
41
+ public:
42
+ SpecDataRuby( VALUE h ) { hash = h; }
43
+
44
+ virtual StrPtr *GetLine( SpecElem *sd, int x, const char **cmt );
45
+ virtual void SetLine( SpecElem *sd, int x, const StrPtr *val,
46
+ Error *e );
47
+
48
+ private:
49
+ VALUE hash;
50
+ StrBuf last;
51
+ };
52
+
@@ -0,0 +1,62 @@
1
+ // vim:ts=8:sw=4:
2
+ /*******************************************************************************
3
+
4
+ Copyright (c) 2011, Perforce Software, Inc. All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
20
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+
27
+ *******************************************************************************/
28
+ #include <ruby.h>
29
+ #ifdef HAVE_RUBY_ENCODING_H
30
+ #include <ruby/encoding.h>
31
+ #endif
32
+ #include "p4utils.h"
33
+
34
+ char *P4Utils::charset = 0;
35
+
36
+ VALUE P4Utils::ruby_string( const char *msg, long len )
37
+ {
38
+ VALUE str;
39
+ // If a length has been passed then use it
40
+ if( len )
41
+ {
42
+ str = rb_str_new( msg, len );
43
+ }
44
+ else
45
+ {
46
+ str = rb_str_new2( msg );
47
+ }
48
+
49
+ // Now check if an encoding should be set for the string.
50
+ #ifdef HAVE_RUBY_ENCODING_H
51
+ if( charset )
52
+ {
53
+ rb_enc_associate(str, rb_enc_find("UTF-8"));
54
+ }
55
+ else
56
+ {
57
+ rb_enc_associate(str, rb_locale_encoding());
58
+ }
59
+ #endif
60
+
61
+ return str;
62
+ }
data/ext/P4/p4utils.h ADDED
@@ -0,0 +1,46 @@
1
+ /*******************************************************************************
2
+
3
+ Copyright (c) 2011, Perforce Software, Inc. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ *******************************************************************************/
27
+
28
+ /*******************************************************************************
29
+ * Name : p4utils.h
30
+ *
31
+ * Author : Jayesh Mistry <jmistry@perforce.com>
32
+ *
33
+ * Description : C++ class with useful methods
34
+ *
35
+ ******************************************************************************/
36
+ class P4Utils {
37
+ public:
38
+ static void SetCharset( const char *cs ) { charset = (char *) cs; };
39
+ static char* GetCharset() { return charset; };
40
+
41
+ static VALUE ruby_string( const char *msg, long len = 0);
42
+
43
+ private:
44
+ static char* charset;
45
+ };
46
+
@@ -0,0 +1,687 @@
1
+ /*******************************************************************************
2
+
3
+ Copyright (c) 2007-2011, Perforce Software, Inc. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ *******************************************************************************/
27
+
28
+ /*******************************************************************************
29
+ * Name : specmgr.cc
30
+ *
31
+ * Description : Ruby bindings for the Perforce API. Class for handling
32
+ * Perforce specs. This class provides other classes with
33
+ * generic support for parsing and formatting Perforce
34
+ * specs.
35
+ *
36
+ ******************************************************************************/
37
+ #include <ctype.h>
38
+ #include <ruby.h>
39
+ #include "p4utils.h"
40
+ #include "undefdups.h"
41
+ #include <p4/clientapi.h>
42
+ #include <p4/strops.h>
43
+ #include <p4/spec.h>
44
+ #include <p4/strtable.h>
45
+ #include "p4rubyconf.h"
46
+ #include "gc_hack.h"
47
+ #include "p4rubydebug.h"
48
+ #include "p4specdata.h"
49
+ #include "specmgr.h"
50
+
51
+ struct defaultspec {
52
+ const char *type;
53
+ const char *spec;
54
+ } speclist[] = {
55
+ {
56
+ "branch",
57
+ "Branch;code:301;rq;ro;fmt:L;len:32;;"
58
+ "Update;code:302;type:date;ro;fmt:L;len:20;;"
59
+ "Access;code:303;type:date;ro;fmt:L;len:20;;"
60
+ "Owner;code:304;fmt:R;len:32;;"
61
+ "Description;code:306;type:text;len:128;;"
62
+ "Options;code:309;type:line;len:32;val:"
63
+ "unlocked/locked;;"
64
+ "View;code:311;type:wlist;words:2;len:64;;"
65
+ },
66
+ {
67
+ "changeX",
68
+ "Change;code:201;rq;ro;fmt:L;seq:1;len:10;;"
69
+ "Date;code:202;type:date;ro;fmt:R;seq:3;len:20;;"
70
+ "Client;code:203;ro;fmt:L;seq:2;len:32;;"
71
+ "User;code:204;ro;fmt:L;seq:4;len:32;;"
72
+ "Status;code:205;ro;fmt:R;seq:5;len:10;;"
73
+ "Type;code:211;seq:6;type:select;fmt:L;len:10;"
74
+ "val:public/restricted;;"
75
+ "Description;code:206;type:text;rq;;"
76
+ "Jobs;code:209;type:wlist;words:2;len:32;;"
77
+ "Files;code:210;type:llist;len:64;;"
78
+ },
79
+ {
80
+ "change",
81
+ "Change;code:201;rq;ro;fmt:L;seq:1;len:10;;"
82
+ "Date;code:202;type:date;ro;fmt:R;seq:3;len:20;;"
83
+ "Client;code:203;ro;fmt:L;seq:2;len:32;;"
84
+ "User;code:204;ro;fmt:L;seq:4;len:32;;"
85
+ "Status;code:205;ro;fmt:R;seq:5;len:10;;"
86
+ "Type;code:211;seq:6;type:select;fmt:L;len:10;"
87
+ "val:public/restricted;;"
88
+ "Description;code:206;type:text;rq;seq:7;;"
89
+ "JobStatus;code:207;fmt:I;type:select;seq:9;;"
90
+ "Jobs;code:208;type:wlist;seq:8;len:32;;"
91
+ "Files;code:210;type:llist;len:64;;"
92
+ },
93
+ {
94
+ "client",
95
+ "Client;code:301;rq;ro;seq:1;len:32;;"
96
+ "Update;code:302;type:date;ro;seq:2;fmt:L;len:20;;"
97
+ "Access;code:303;type:date;ro;seq:4;fmt:L;len:20;;"
98
+ "Owner;code:304;seq:3;fmt:R;len:32;;"
99
+ "Host;code:305;seq:5;fmt:R;len:32;;"
100
+ "Description;code:306;type:text;len:128;;"
101
+ "Root;code:307;rq;type:line;len:64;;"
102
+ "AltRoots;code:308;type:llist;len:64;;"
103
+ "Options;code:309;type:line;len:64;val:"
104
+ "noallwrite/allwrite,noclobber/clobber,nocompress/compress,"
105
+ "unlocked/locked,nomodtime/modtime,normdir/rmdir;;"
106
+ "SubmitOptions;code:313;type:select;fmt:L;len:25;val:"
107
+ "submitunchanged/submitunchanged+reopen/revertunchanged/"
108
+ "revertunchanged+reopen/leaveunchanged/leaveunchanged+reopen;;"
109
+ "LineEnd;code:310;type:select;fmt:L;len:12;val:"
110
+ "local/unix/mac/win/share;;"
111
+ "Stream;code:314;type:line;len:64;;"
112
+ "StreamAtChange;code:316;type:line;len:64;;"
113
+ "ServerID;code:315;type:line;ro;len:64;;"
114
+ "View;code:311;type:wlist;words:2;len:64;;"
115
+ "ChangeView;code:317;type:llist;len:64;;"
116
+ },
117
+ {
118
+ "clientX",
119
+ "Client;code:301;rq;ro;seq:1;len:32;;"
120
+ "Update;code:302;type:date;ro;seq:2;fmt:L;len:20;;"
121
+ "Access;code:303;type:date;ro;seq:4;fmt:L;len:20;;"
122
+ "Owner;code:304;seq:3;fmt:R;len:32;;"
123
+ "Host;code:305;seq:5;fmt:R;len:32;;"
124
+ "Description;code:306;type:text;len:128;;"
125
+ "Root;code:307;rq;type:line;len:64;;"
126
+ "AltRoots;code:308;type:llist;len:64;;"
127
+ "Options;code:309;type:line;len:64;val:"
128
+ "noallwrite/allwrite,noclobber/clobber,nocompress/compress,"
129
+ "unlocked/locked,nomodtime/modtime,normdir/rmdir;;"
130
+ "SubmitOptions;code:313;type:select;fmt:L;len:25;val:"
131
+ "submitunchanged/submitunchanged+reopen/revertunchanged/"
132
+ "revertunchanged+reopen/leaveunchanged/leaveunchanged+reopen;;"
133
+ "LineEnd;code:310;type:select;fmt:L;len:12;val:"
134
+ "local/unix/mac/win/share;;"
135
+ "View;code:311;type:wlist;words:2;len:64;;"
136
+ },
137
+ {
138
+ "clientSpecing021",
139
+ "Client;code:301;rq;ro;len:32;;"
140
+ "Update;code:302;type:date;ro;len:20;;"
141
+ "Access;code:303;type:date;ro;len:20;;"
142
+ "Owner;code:304;len:32;;"
143
+ "Host;code:305;len:32;;"
144
+ "Description;code:306;type:text;len:128;;"
145
+ "Root;code:307;rq;type:line;len:64;;"
146
+ "AltRoots;code:308;type:text;len:64;;"
147
+ "Options;code:309;type:line;len:64;val:"
148
+ "noallwrite/allwrite,noclobber/clobber,nocompress/compress,"
149
+ "unlocked/locked,nomodtime/modtime,normdir/rmdir;;"
150
+ "LineEnd;code:310;type:select;len:12;val:local/unix/mac/win/share;;"
151
+ "View;code:311;type:wlist;words:2;len:64;;"
152
+ },
153
+ {
154
+ "depot",
155
+ "Depot;code:251;rq;ro;len:32;;"
156
+ "Owner;code:252;len:32;;"
157
+ "Date;code:253;type:date;ro;len:20;;"
158
+ "Description;code:254;type:text;len:128;;"
159
+ "Type;code:255;rq;len:10;;"
160
+ "Address;code:256;len:64;;"
161
+ "Suffix;code:258;len:64;;"
162
+ "Map;code:257;rq;len:64;;"
163
+ "SpecMap;code:259;type:wlist;len:64;;"
164
+ },
165
+ {
166
+ "group",
167
+ "Group;code:401;rq;ro;len:32;;"
168
+ "MaxResults;code:402;type:word;len:12;;"
169
+ "MaxScanRows;code:403;type:word;len:12;;"
170
+ "MaxLockTime;code:407;type:word;len:12;;"
171
+ "Timeout;code:406;type:word;len:12;;"
172
+ "PasswordTimeout;code:409;type:word;len:12;;"
173
+ "Subgroups;code:404;type:wlist;len:32;opt:default;;"
174
+ "Owners;code:408;type:wlist;len:32;opt:default;;"
175
+ "Users;code:405;type:wlist;len:32;opt:default;;"
176
+ },
177
+ {
178
+ "job",
179
+ "Job;code:101;rq;len:32;;"
180
+ "Status;code:102;type:select;rq;len:10;"
181
+ "pre:open;val:open/suspended/closed;;"
182
+ "User;code:103;rq;len:32;pre:$user;;"
183
+ "Date;code:104;type:date;ro;len:20;pre:$now;;"
184
+ "Description;code:105;type:text;rq;pre:$blank;;"
185
+ },
186
+ {
187
+ "label",
188
+ "Label;code:301;rq;ro;fmt:L;len:32;;"
189
+ "Update;code:302;type:date;ro;fmt:L;len:20;;"
190
+ "Access;code:303;type:date;ro;fmt:L;len:20;;"
191
+ "Owner;code:304;fmt:R;len:32;;"
192
+ "Description;code:306;type:text;len:128;;"
193
+ "Options;code:309;type:line;len:64;val:"
194
+ "unlocked/locked,noautoreload/autoreload;;"
195
+ "Revision;code:312;type:word;words:1;len:64;;"
196
+ "ServerID;code:315;type:line;ro;len:64;;"
197
+ "View;code:311;type:wlist;len:64;;"
198
+ },
199
+ {
200
+ "ldap",
201
+ "Name;code:801;rq;len:32;;"
202
+ "Host;code:802;rq;type:word;words:1;len:128;;"
203
+ "Port;code:803;rq;type:word;words:1;len:5;;"
204
+ "Encryption;code:804;rq;len:10;val:"
205
+ "none/ssl/tls;;"
206
+ "BindMethod;code:805;rq;len:10;val:"
207
+ "simple/search/sasl;;"
208
+ "SimplePattern;code:806;type:line;len:128;;"
209
+ "SearchBaseDN;code:807;type:line;len:128;;"
210
+ "SearchFilter;code:808;type:line;len:128;;"
211
+ "SearchScope;code:809;len:10;val:"
212
+ "baseonly/children/subtree;;"
213
+ "SearchBindDN;code:810;type:line;len:128;;"
214
+ "SearchPasswd;code:811;type:line;len:128;;"
215
+ "SaslRealm;code:812;type:word;words:1;len:128;;"
216
+ "GroupBaseDN;code:813;type:line;len:128;;"
217
+ "GroupSearchFilter;code:814;type:line;len:128;;"
218
+ "GroupSearchScope;code:815;len:10;val:"
219
+ "baseonly/children/subtree;;"
220
+ },
221
+ {
222
+ "license",
223
+ "License;code:451;len:32;;"
224
+ "License-Expires;code:452;len:10;;"
225
+ "Support-Expires;code:453;len:10;;"
226
+ "Customer;code:454;type:line;len:128;;"
227
+ "Application;code:455;len:32;;"
228
+ "IPaddress;code:456;len:24;;"
229
+ "IPservice;code:461;type:wlist;len:24;;"
230
+ "Platform;code:457;len:32;;"
231
+ "Clients;code:458;len:8;;"
232
+ "Users;code:459;len:8;;"
233
+ "Files;code:460;len:8;;"
234
+ },
235
+ {
236
+ "protect",
237
+ "Protections;code:501;type:wlist;words:5;opt:default;len:64;;"
238
+ },
239
+ {
240
+ "specW",
241
+ "Fields;code:351;type:wlist;words:5;rq;;"
242
+ "Required;code:357;type:wlist;;"
243
+ "Readonly;code:358;type:wlist;;"
244
+ "Words;code:352;type:wlist;words:2;;"
245
+ "Formats;code:353;type:wlist;words:3;;"
246
+ "Values;code:354;type:wlist;words:2;;"
247
+ "Presets;code:355;type:wlist;words:2;;"
248
+ "Comments;code:356;type:text;;"
249
+ },
250
+ {
251
+ "spec",
252
+ "Fields;code:351;type:wlist;words:5;rq;;"
253
+ "Words;code:352;type:wlist;words:2;;"
254
+ "Formats;code:353;type:wlist;words:3;;"
255
+ "Values;code:354;type:wlist;words:2;;"
256
+ "Presets;code:355;type:wlist;words:2;;"
257
+ "Comments;code:356;type:text;;"
258
+ },
259
+ {
260
+ "stream",
261
+ "Stream;code:701;rq;ro;len:64;;"
262
+ "Update;code:705;type:date;ro;fmt:L;len:20;;"
263
+ "Access;code:706;type:date;ro;fmt:L;len:20;;"
264
+ "Owner;code:704;len:32;;"
265
+ "Name;code:703;rq;type:line;len:32;;"
266
+ "Parent;code:702;rq;len:64;;"
267
+ "Type;code:708;rq;len:32;;"
268
+ "Description;code:709;type:text;len:128;;"
269
+ "Options;code:707;type:line;len:64;val:"
270
+ "allsubmit/ownersubmit,unlocked/locked,"
271
+ "toparent/notoparent,fromparent/nofromparent;;"
272
+ "Paths;code:710;rq;type:wlist;words:2;maxwords:3;len:64;;"
273
+ "Remapped;code:711;type:wlist;words:2;len:64;;"
274
+ "Ignored;code:712;type:wlist;words:1;len:64;;"
275
+ "View;code:713;type:wlist;words:2;len:64;;"
276
+ "ChangeView;code:714;type:llist;ro;len:64;;"
277
+ },
278
+ {
279
+ "triggers",
280
+ "Triggers;code:551;type:wlist;words:4;len:64;opt:default;"
281
+ },
282
+ {
283
+ "typemap",
284
+ "TypeMap;code:601;type:wlist;words:2;len:64;opt:default;"
285
+ },
286
+ {
287
+ "user",
288
+ "User;code:651;rq;ro;seq:1;len:32;;"
289
+ "Type;code:659;ro;fmt:R;len:10;;"
290
+ "Email;code:652;fmt:R;rq;seq:3;len:32;;"
291
+ "Update;code:653;fmt:L;type:date;ro;seq:2;len:20;;"
292
+ "Access;code:654;fmt:L;type:date;ro;len:20;;"
293
+ "FullName;code:655;fmt:R;type:line;rq;len:32;;"
294
+ "JobView;code:656;type:line;len:64;;"
295
+ "Password;code:657;len:32;;"
296
+ "AuthMethod;code:662;fmt:L;len:10;val:perforce/ldap;;"
297
+ "Reviews;code:658;type:wlist;len:64;;"
298
+ },
299
+ {
300
+ "server",
301
+ "ServerID;code:751;rq;ro;len:32;;"
302
+ "Type;code:752;rq;len:32;;"
303
+ "Name;code:753;type:line;len:32;;"
304
+ "Address;code:754;type:line;len:32;;"
305
+ "Services;code:755;rq;len:128;;"
306
+ "Description;code:756;type:text;len:128;;"
307
+ "User;code:760;type:line;len:64;;"
308
+ "ClientDataFilter;code:757;type:wlist;len:64;;"
309
+ "RevisionDataFilter;code:758;type:wlist;len:64;;"
310
+ "ArchiveDataFilter;code:759;type:wlist;len:64;;"
311
+ },
312
+ { 0, 0 }
313
+ };
314
+
315
+ SpecMgr::SpecMgr()
316
+ {
317
+ debug = 0;
318
+ specs = 0;
319
+ Reset();
320
+ }
321
+
322
+ SpecMgr::~SpecMgr()
323
+ {
324
+ delete specs;
325
+ }
326
+
327
+ void
328
+ SpecMgr::AddSpecDef( const char *type, StrPtr &specDef )
329
+ {
330
+ if( specs->GetVar( type ) )
331
+ specs->RemoveVar( type );
332
+ specs->SetVar( type, specDef );
333
+ }
334
+
335
+ void
336
+ SpecMgr::AddSpecDef( const char *type, const char *specDef )
337
+ {
338
+ if( specs->GetVar( type ) )
339
+ specs->RemoveVar( type );
340
+ specs->SetVar( type, specDef );
341
+ }
342
+
343
+
344
+ void
345
+ SpecMgr::Reset()
346
+ {
347
+ delete specs;
348
+ specs = new StrBufDict;
349
+
350
+ for( struct defaultspec *sp = &speclist[ 0 ]; sp->type; sp++ )
351
+ AddSpecDef( sp->type, sp->spec );
352
+
353
+ }
354
+
355
+ int
356
+ SpecMgr::HaveSpecDef( const char *type )
357
+ {
358
+ return specs->GetVar( type ) != 0;
359
+ }
360
+
361
+ //
362
+ // Convert a Perforce StrDict into a Ruby hash. Convert multi-level
363
+ // data (Files0, Files1 etc. ) into (nested) array members of the hash.
364
+ //
365
+
366
+ VALUE
367
+ SpecMgr::StrDictToHash( StrDict *dict, VALUE hash )
368
+ {
369
+ StrRef var, val;
370
+ int i;
371
+
372
+ if( hash == Qnil )
373
+ hash = rb_hash_new();
374
+
375
+ for ( i = 0; dict->GetVar( i, var, val ); i++ )
376
+ {
377
+ if ( var == "specdef" || var == "func" || var == "specFormatted" )
378
+ continue;
379
+
380
+ InsertItem( hash, &var, &val );
381
+ }
382
+ return hash;
383
+ }
384
+
385
+ //
386
+ // Convert a Perforce StrDict into a P4::Spec object
387
+ //
388
+
389
+ VALUE
390
+ SpecMgr::StrDictToSpec( StrDict *dict, StrPtr *specDef )
391
+ {
392
+
393
+ // This converts it to a string, and then to a hash, so we go from one
394
+ // type of dictionary to another, via an intermediate form (a StrBuf).
395
+
396
+ Error e;
397
+ SpecDataTable dictData( dict );
398
+ #if P4APIVER_ID >= 513538
399
+ Spec s( specDef->Text(), "", &e );
400
+ #else
401
+ Spec s( specDef->Text(), "" );
402
+ #endif
403
+ StrBuf form;
404
+
405
+ if( e.Test() ) return Qfalse;
406
+
407
+ // Format the StrDict into a StrBuf object
408
+ s.Format( &dictData, &form );
409
+
410
+ // Now parse the StrBuf into a new P4::Spec object
411
+ VALUE spec = NewSpec( specDef );
412
+ SpecDataRuby hashData( spec );
413
+
414
+ s.ParseNoValid( form.Text(), &hashData, &e );
415
+ if( e.Test() ) return Qfalse;
416
+
417
+ // Now see if there are any extraTag fields as we'll need to
418
+ // add those fields into our output. Just iterate over them
419
+ // extracting the fields and inserting them as we go.
420
+ int i = 0;
421
+ StrRef et("extraTag" );
422
+ for( i = 0; ; i++ )
423
+ {
424
+ StrBuf tag;
425
+ StrPtr *var;
426
+ StrPtr *val;
427
+
428
+ tag << et << i;
429
+ if( !(var = dict->GetVar( tag ) ) )
430
+ break;
431
+
432
+ val = dict->GetVar( *var );
433
+ if( !val ) continue;
434
+
435
+ InsertItem( spec, var, val );
436
+ }
437
+
438
+ return spec;
439
+ }
440
+
441
+ VALUE
442
+ SpecMgr::StringToSpec( const char *type, const char *form, Error *e )
443
+ {
444
+
445
+ StrPtr * specDef = specs->GetVar( type );
446
+ VALUE hash = NewSpec( specDef );
447
+ SpecDataRuby specData( hash );
448
+ #if P4APIVER_ID >= 513538
449
+ Spec s( specDef->Text(), "", e );
450
+ #else
451
+ Spec s( specDef->Text(), "" );
452
+ #endif
453
+
454
+ if( !e->Test() )
455
+ s.ParseNoValid( form, &specData, e );
456
+
457
+ if ( e->Test() )
458
+ return Qfalse;
459
+
460
+ return hash;
461
+ }
462
+
463
+
464
+ //
465
+ // Format routine. updates a StrBuf object with the form content.
466
+ // The StrBuf can then be converted to a Ruby string where required.
467
+ //
468
+ void
469
+ SpecMgr::SpecToString( const char *type, VALUE hash, StrBuf &b, Error *e )
470
+ {
471
+
472
+ StrBuf buf;
473
+ StrPtr * specDef = specs->GetVar( type );
474
+ if ( !specDef )
475
+ {
476
+ e->Set( E_FAILED, "No specdef available. Cannot convert hash to a "
477
+ "Perforce form" );
478
+ return;
479
+ }
480
+
481
+ SpecDataRuby specData( hash );
482
+ #if P4APIVER_ID >= 513538
483
+ Spec s( specDef->Text(), "", e );
484
+ #else
485
+ Spec s( specDef->Text(), "" );
486
+ #endif
487
+
488
+ if( e->Test() ) return;
489
+
490
+ s.Format( &specData, &b );
491
+ }
492
+
493
+ //
494
+ // This method returns a hash describing the valid fields in the spec. To
495
+ // make it easy on our users, we map the lowercase name to the name defined
496
+ // in the spec. Thus, the users can always user lowercase, and if the field
497
+ // should be in mixed case, it will be. See P4::Spec::method_missing
498
+ //
499
+
500
+ VALUE
501
+ SpecMgr::SpecFields( const char *type )
502
+ {
503
+ return SpecFields( specs->GetVar( type ) );
504
+ }
505
+
506
+ VALUE
507
+ SpecMgr::SpecFields( StrPtr *specDef )
508
+ {
509
+ if( !specDef ) return Qnil;
510
+
511
+ //
512
+ // Here we abuse the fact that SpecElem::tag is public, even though it's
513
+ // only supposed to be public to SpecData's subclasses. It's hard to
514
+ // see that changing anytime soon, and it makes this so simple and
515
+ // reliable. So...
516
+ //
517
+ VALUE hash = rb_hash_new();
518
+ Error e;
519
+
520
+ #if P4APIVER_ID >= 513538
521
+ Spec s( specDef->Text(), "", &e );
522
+ #else
523
+ Spec s( specDef->Text(), "" );
524
+ #endif
525
+ if( e.Test() ) return Qnil;
526
+
527
+ for( int i = 0; i < s.Count(); i++ )
528
+ {
529
+ StrBuf k;
530
+ StrBuf v;
531
+ SpecElem * se = s.Get( i );
532
+
533
+ v = se->tag;
534
+ k = v;
535
+ StrOps::Lower( k );
536
+
537
+ rb_hash_aset(hash,
538
+ P4Utils::ruby_string( k.Text(), k.Length() ),
539
+ P4Utils::ruby_string( v.Text(), v.Length() ) );
540
+ }
541
+ return hash;
542
+ }
543
+
544
+ //
545
+ // Split a key into its base name and its index. i.e. for a key "how1,0"
546
+ // the base name is "how" and they index is "1,0". We work backwards from
547
+ // the end of the key looking for the first char that is neither a
548
+ // digit, nor a comma.
549
+ //
550
+
551
+ void
552
+ SpecMgr::SplitKey( const StrPtr *key, StrBuf &base, StrBuf &index )
553
+ {
554
+ int i = 0;
555
+
556
+ base = *key;
557
+ index = "";
558
+ for ( i = key->Length(); i; i-- )
559
+ {
560
+ char prev = (*key)[ i-1 ];
561
+ if ( !isdigit( prev ) && prev != ',' )
562
+ {
563
+ base.Set( key->Text(), i );
564
+ index.Set( key->Text() + i );
565
+ break;
566
+ }
567
+ }
568
+ }
569
+
570
+ //
571
+ // Insert an element into the response structure. The element may need to
572
+ // be inserted into an array nested deeply within the enclosing hash.
573
+ //
574
+
575
+ void
576
+ SpecMgr::InsertItem( VALUE hash, const StrPtr *var, const StrPtr *val )
577
+ {
578
+ VALUE ary = 0;
579
+ VALUE tary = 0;
580
+ VALUE key;
581
+ ID idLength = rb_intern( "length" );
582
+ StrBuf base, index;
583
+ StrRef comma( "," );
584
+
585
+ SplitKey( var, base, index );
586
+
587
+ // If there's no index, then we insert into the top level hash
588
+ // but if the key is already defined then we need to rename the key. This
589
+ // is probably one of those special keys like otherOpen which can be
590
+ // both an array element and a scalar. The scalar comes last, so we
591
+ // just rename it to "otherOpens" to avoid trashing the previous key
592
+ // value
593
+ if ( index == "" )
594
+ {
595
+ ID idHasKey = rb_intern( "has_key?");
596
+ ID idPlus = rb_intern( "+" );
597
+
598
+ key = P4Utils::ruby_string( var->Text() );
599
+ if ( rb_funcall( hash, idHasKey, 1, key ) == Qtrue )
600
+ key = rb_funcall( key, idPlus, 1, P4Utils::ruby_string( "s" ) );
601
+
602
+ if( P4RDB_DATA )
603
+ fprintf( stderr, "... %s -> %s\n", StringValuePtr( key ), val->Text() );
604
+
605
+ rb_hash_aset( hash, key, P4Utils::ruby_string( val->Text() ) );
606
+ return;
607
+ }
608
+
609
+ //
610
+ // Get or create the parent array from the hash.
611
+ //
612
+ key = P4Utils::ruby_string( base.Text() );
613
+ ary = rb_hash_aref( hash, key );
614
+
615
+ if ( Qnil == ary )
616
+ {
617
+ ary = rb_ary_new();
618
+ rb_hash_aset( hash, key, ary );
619
+ }
620
+ else if( rb_obj_is_kind_of( ary, rb_cArray ) != Qtrue )
621
+ {
622
+ //
623
+ // There's an index in our var name, but the name is already defined
624
+ // and the value it contains is not an array. This means we've got a
625
+ // name collision. This can happen in 'p4 diff2' for example, when
626
+ // one file gets 'depotFile' and the other gets 'depotFile2'. In
627
+ // these cases it makes sense to keep the structure flat so we
628
+ // just use the raw variable name.
629
+ //
630
+ if( P4RDB_DATA )
631
+ fprintf( stderr, "... %s -> %s\n", var->Text(), val->Text() );
632
+
633
+ rb_hash_aset( hash, P4Utils::ruby_string( var->Text() ) ,
634
+ P4Utils::ruby_string( val->Text() ) );
635
+ return;
636
+ }
637
+
638
+ // The index may be a simple digit, or it could be a comma separated
639
+ // list of digits. For each "level" in the index, we need a containing
640
+ // array.
641
+ if( P4RDB_DATA )
642
+ fprintf( stderr, "... %s -> [", base.Text() );
643
+
644
+ for( const char *c = 0 ; ( c = index.Contains( comma ) ); )
645
+ {
646
+ StrBuf level;
647
+ level.Set( index.Text(), c - index.Text() );
648
+ index.Set( c + 1 );
649
+
650
+ // Found another level so we need to get/create a nested array
651
+ // under the current entry. We use the level as an index so that
652
+ // missing entries are left empty deliberately.
653
+
654
+ tary = rb_ary_entry( ary, level.Atoi() );
655
+ if ( ! RTEST( tary ) )
656
+ {
657
+ tary = rb_ary_new();
658
+ rb_ary_store( ary, level.Atoi(), tary );
659
+ }
660
+ if( P4RDB_DATA )
661
+ fprintf( stderr, "%s][", level.Text() );
662
+ ary = tary;
663
+ }
664
+ int pos = index.Atoi();
665
+
666
+ if( P4RDB_DATA )
667
+ fprintf( stderr, "%d] = %s\n", pos, val->Text() );
668
+
669
+ rb_ary_store( ary, pos, P4Utils::ruby_string( val->Text() ) );
670
+ }
671
+
672
+ //
673
+ // Create a new P4::Spec object and return it.
674
+ //
675
+
676
+ VALUE
677
+ SpecMgr::NewSpec( StrPtr *specDef )
678
+ {
679
+ ID idNew = rb_intern( "new" );
680
+ ID idP4 = rb_intern( "P4" );
681
+ ID idP4Spec = rb_intern( "Spec" );
682
+ VALUE cP4 = rb_const_get_at( rb_cObject, idP4 );
683
+ VALUE cP4Spec = rb_const_get_at( cP4, idP4Spec );
684
+ VALUE fields = SpecFields( specDef );
685
+
686
+ return rb_funcall( cP4Spec, idNew, 1, fields );
687
+ }