1 /*
2  * syck.h
3  *
4  * $Author$
5  * $Date$
6  *
7  * Copyright (C) 2003 why the lucky stiff
8  */
9 
10 #ifndef SYCK_H
11 #define SYCK_H
12 
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16 
17 #define SYCK_YAML_MAJOR 1
18 #define SYCK_YAML_MINOR 0
19 
20 #define SYCK_VERSION    "0.70"
21 #define YAML_DOMAIN     "yaml.org,2002"
22 
23 #ifdef HAVE_STDLIB_H
24 # include <stdlib.h>
25 #endif
26 
27 #ifdef HAVE_STRING_H
28 # include <string.h>
29 #else
30 # include <strings.h>
31 #endif
32 
33 #ifdef HAVE_INTRINSICS_H
34 # include <intrinsics.h>
35 #endif
36 
37 #include <stddef.h>
38 #include <stdio.h>
39 #include <ctype.h>
40 #ifdef HAVE_ST_H
41 #include <st.h>
42 #else
43 #include "syck_st.h"
44 #endif
45 
46 #if defined(__cplusplus)
47 extern "C" {
48 #endif
49 
50 /*
51  * Memory Allocation
52  */
53 #if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
54 #include <alloca.h>
55 #endif
56 
57 #if DEBUG
58   void syck_assert( const char *, unsigned );
59 # define ASSERT(f) \
60     if ( f ) \
61         {}   \
62     else     \
63         syck_assert( __FILE__, __LINE__ )
64 #else
65 # define ASSERT(f)
66 #endif
67 
68 #ifndef NULL
69 # define NULL (void *)0
70 #endif
71 
72 #define ALLOC_CT 8
73 #define SYCK_BUFFERSIZE 4096
74 #define S_ALLOC_N(type,n) (type*)malloc(sizeof(type)*(n))
75 #define S_ALLOC(type) (type*)malloc(sizeof(type))
76 #define S_REALLOC_N(var,type,n) (var)=(type*)realloc((char*)(var),sizeof(type)*(n))
77 #define S_FREE(n) free(n); n = NULL;
78 
79 #define S_ALLOCA_N(type,n) (type*)alloca(sizeof(type)*(n))
80 
81 #define S_MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(n))
82 #define S_MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(n))
83 #define S_MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n))
84 #define S_MEMCMP(p1,p2,type,n) memcmp((p1), (p2), sizeof(type)*(n))
85 
86 #define BLOCK_FOLD  10
87 #define BLOCK_LIT   20
88 #define BLOCK_PLAIN 30
89 #define NL_CHOMP    40
90 #define NL_KEEP     50
91 
92 /*
93  * Node definitions
94  */
95 #ifndef ST_DATA_T_DEFINED
96 typedef long st_data_t;
97 #endif
98 
99 #define SYMID unsigned long
100 
101 typedef struct _syck_node SyckNode;
102 
103 enum syck_kind_tag {
104     syck_map_kind,
105     syck_seq_kind,
106     syck_str_kind
107 };
108 
109 enum map_part {
110     map_key,
111     map_value
112 };
113 
114 enum map_style {
115     map_none,
116     map_inline
117 };
118 
119 enum seq_style {
120     seq_none,
121     seq_inline
122 };
123 
124 enum scalar_style {
125     scalar_none,
126     scalar_1quote,
127     scalar_2quote,
128     scalar_fold,
129     scalar_literal,
130     scalar_plain
131 };
132 
133 /*
134  * Node metadata struct
135  */
136 struct _syck_node {
137     /* Symbol table ID */
138     SYMID id;
139     /* Underlying kind */
140     enum syck_kind_tag kind;
141     /* Fully qualified tag-uri for type */
142     char *type_id;
143     /* Anchor name */
144     char *anchor;
145     union {
146         /* Storage for map data */
147         struct SyckMap {
148             enum map_style style;
149             SYMID *keys;
150             SYMID *values;
151             long capa;
152             long idx;
153         } *pairs;
154         /* Storage for sequence data */
155         struct SyckSeq {
156             enum seq_style style;
157             SYMID *items;
158             long capa;
159             long idx;
160         } *list;
161         /* Storage for string data */
162         struct SyckStr {
163             enum scalar_style style;
164             char *ptr;
165             long len;
166         } *str;
167     } data;
168     /* Shortcut node */
169     void *shortcut;
170 };
171 
172 /*
173  * Parser definitions
174  */
175 typedef struct _syck_parser SyckParser;
176 typedef struct _syck_file SyckIoFile;
177 typedef struct _syck_str SyckIoStr;
178 typedef struct _syck_level SyckLevel;
179 
180 typedef SYMID (*SyckNodeHandler)(SyckParser *, SyckNode *);
181 typedef void (*SyckErrorHandler)(SyckParser *, const char *);
182 typedef SyckNode * (*SyckBadAnchorHandler)(SyckParser *, const char *);
183 typedef long (*SyckIoFileRead)(char *, SyckIoFile *, long, long);
184 typedef long (*SyckIoStrRead)(char *, SyckIoStr *, long, long);
185 
186 enum syck_io_type {
187     syck_io_str,
188     syck_io_file
189 };
190 
191 enum syck_parser_input {
192     syck_yaml_utf8,
193     syck_yaml_utf16,
194     syck_yaml_utf32,
195     syck_bytecode_utf8
196 };
197 
198 enum syck_level_status {
199     syck_lvl_header,
200     syck_lvl_doc,
201     syck_lvl_open,
202     syck_lvl_seq,
203     syck_lvl_map,
204     syck_lvl_block,
205     syck_lvl_str,
206     syck_lvl_iseq,
207     syck_lvl_imap,
208     syck_lvl_end,
209     syck_lvl_pause,
210     syck_lvl_anctag,
211     syck_lvl_mapx,
212     syck_lvl_seqx
213 };
214 
215 /*
216  * Parser structs
217  */
218 struct _syck_file {
219     /* File pointer */
220     FILE *ptr;
221     /* Function which FILE -> buffer */
222     SyckIoFileRead read;
223 };
224 
225 struct _syck_str {
226     /* String buffer pointers */
227     const char *beg, *ptr, *end;
228     /* Function which string -> buffer */
229     SyckIoStrRead read;
230 };
231 
232 struct _syck_level {
233     /* Indent */
234     int spaces;
235     /* Counts nodes emitted at this level, useful for parsing
236      * keys and pairs in bytecode */
237     int ncount;
238     /* Does node have anchors or tags? */
239     int anctag;
240     /* Domain prefixing at the given level */
241     char *domain;
242     /* Keeps a node status */
243     enum syck_level_status status;
244 };
245 
246 struct _syck_parser {
247     /* Root node */
248     SYMID root, root_on_error;
249     /* Implicit typing flag */
250     int implicit_typing, taguri_expansion;
251     /* Scripting language function to handle nodes */
252     SyckNodeHandler handler;
253     /* Error handler */
254     SyckErrorHandler error_handler;
255     /* InvalidAnchor handler */
256     SyckBadAnchorHandler bad_anchor_handler;
257     /* Parser input type */
258     enum syck_parser_input input_type;
259     /* IO type */
260     enum syck_io_type io_type;
261     /* Custom buffer size */
262     size_t bufsize;
263     /* Buffer pointers */
264     char *buffer, *linectptr, *lineptr, *toktmp, *token, *cursor, *marker, *limit;
265     /* Line counter */
266     int linect;
267     /* Last token from yylex() */
268     int last_token;
269     /* Force a token upon next call to yylex() */
270     int force_token;
271     /* EOF flag */
272     int eof;
273     union {
274         SyckIoFile *file;
275         SyckIoStr *str;
276     } io;
277     /* Symbol table for anchors */
278     st_table *anchors, *bad_anchors;
279     /* Optional symbol table for SYMIDs */
280     st_table *syms;
281     /* Levels of indentation */
282     SyckLevel *levels;
283     int lvl_idx;
284     int lvl_capa;
285     /* Pointer for extension's use */
286     void *bonus;
287 };
288 
289 /*
290  * Emitter definitions
291  */
292 typedef struct _syck_emitter SyckEmitter;
293 typedef struct _syck_emitter_node SyckEmitterNode;
294 
295 typedef void (*SyckOutputHandler)(SyckEmitter *, const char *, long);
296 typedef void (*SyckEmitterHandler)(SyckEmitter *, st_data_t);
297 
298 enum doc_stage {
299     doc_open,
300     doc_processing
301 };
302 
303 /*
304  * Emitter struct
305  */
306 struct _syck_emitter {
307     /* Headerless doc flag */
308     int headless;
309     /* Force header? */
310     int use_header;
311     /* Force version? */
312     int use_version;
313     /* Sort hash keys */
314     int sort_keys;
315     /* Anchor format */
316     char *anchor_format;
317     /* Explicit typing on all collections? */
318     int explicit_typing;
319     /* Best width on folded scalars */
320     int best_width;
321     /* Use literal[1] or folded[2] blocks on all text? */
322     enum scalar_style style;
323     /* Stage of written document */
324     enum doc_stage stage;
325     /* Level counter */
326     int level;
327     /* Default indentation */
328     int indent;
329     /* Object ignore ID */
330     SYMID ignore_id;
331     /* Symbol table for anchors */
332     st_table *markers, *anchors, *anchored;
333     /* Custom buffer size */
334     size_t bufsize;
335     /* Buffer */
336     char *buffer, *marker;
337     /* Absolute position of the buffer */
338     long bufpos;
339     /* Handler for emitter nodes */
340     SyckEmitterHandler emitter_handler;
341     /* Handler for output */
342     SyckOutputHandler output_handler;
343     /* Levels of indentation */
344     SyckLevel *levels;
345     int lvl_idx;
346     int lvl_capa;
347     /* Pointer for extension's use */
348     void *bonus;
349 };
350 
351 /*
352  * Emitter node metadata struct
353  */
354 struct _syck_emitter_node {
355     /* Node buffer position */
356     long pos;
357     /* Current indent */
358     long indent;
359     /* Collection? */
360     int is_shortcut;
361 };
362 
363 /*
364  * Handler prototypes
365  */
366 SYMID syck_hdlr_add_node( SyckParser *, SyckNode * );
367 SyckNode *syck_hdlr_add_anchor( SyckParser *, char *, SyckNode * );
368 void syck_hdlr_remove_anchor( SyckParser *, char * );
369 SyckNode *syck_hdlr_get_anchor( SyckParser *, char * );
370 void syck_add_transfer( char *, SyckNode *, int );
371 char *syck_xprivate( char *, int );
372 char *syck_taguri( const char *, const char *, int );
373 int syck_tagcmp( const char *, const char * );
374 int syck_add_sym( SyckParser *, char * );
375 int syck_lookup_sym( SyckParser *, SYMID, char ** );
376 int syck_try_implicit( SyckNode * );
377 char *syck_type_id_to_uri( char * );
378 void try_tag_implicit( SyckNode *, int );
379 char *syck_match_implicit( const char *, size_t );
380 
381 /*
382  * API prototypes
383  */
384 char *syck_strndup( const char *, long );
385 long syck_io_file_read( char *, SyckIoFile *, long, long );
386 long syck_io_str_read( char *, SyckIoStr *, long, long );
387 char *syck_base64enc( const char *, long );
388 char *syck_base64dec( const char *, long );
389 SyckEmitter *syck_new_emitter( void );
390 SYMID syck_emitter_mark_node( SyckEmitter *, st_data_t );
391 void syck_emitter_ignore_id( SyckEmitter *, SYMID );
392 void syck_output_handler( SyckEmitter *, SyckOutputHandler );
393 void syck_emitter_handler( SyckEmitter *, SyckEmitterHandler );
394 void syck_free_emitter( SyckEmitter * );
395 void syck_emitter_clear( SyckEmitter * );
396 void syck_emitter_write( SyckEmitter *, const char *, long );
397 void syck_emitter_escape( SyckEmitter *, const char *, long );
398 void syck_emitter_flush( SyckEmitter *, long );
399 void syck_emit( SyckEmitter *, st_data_t );
400 void syck_emit_scalar( SyckEmitter *, const char *, enum scalar_style, int, int, char, const char *, long );
401 void syck_emit_1quoted( SyckEmitter *, int, const char *, long );
402 void syck_emit_2quoted( SyckEmitter *, int, const char *, long );
403 void syck_emit_folded( SyckEmitter *, int, char, const char *, long );
404 void syck_emit_literal( SyckEmitter *, char, const char *, long );
405 void syck_emit_seq( SyckEmitter *, const char *, enum seq_style );
406 void syck_emit_item( SyckEmitter *, st_data_t );
407 void syck_emit_map( SyckEmitter *, const char *, enum map_style );
408 void syck_emit_end( SyckEmitter * );
409 void syck_emit_tag( SyckEmitter *, const char *, const char * );
410 void syck_emit_indent( SyckEmitter * );
411 SyckLevel *syck_emitter_current_level( SyckEmitter * );
412 SyckLevel *syck_emitter_parent_level( SyckEmitter * );
413 void syck_emitter_pop_level( SyckEmitter * );
414 void syck_emitter_add_level( SyckEmitter *, int, enum syck_level_status );
415 void syck_emitter_reset_levels( SyckEmitter * );
416 SyckParser *syck_new_parser();
417 void syck_free_parser( SyckParser * );
418 void syck_parser_set_root_on_error( SyckParser *, SYMID );
419 void syck_parser_implicit_typing( SyckParser *, int );
420 void syck_parser_taguri_expansion( SyckParser *, int );
421 int syck_scan_scalar( int, const char *, long );
422 void syck_parser_handler( SyckParser *, SyckNodeHandler );
423 void syck_parser_error_handler( SyckParser *, SyckErrorHandler );
424 void syck_parser_bad_anchor_handler( SyckParser *, SyckBadAnchorHandler );
425 void syck_parser_file( SyckParser *, FILE *, SyckIoFileRead );
426 void syck_parser_str( SyckParser *, const char *, long, SyckIoStrRead );
427 void syck_parser_str_auto( SyckParser *, const char *, SyckIoStrRead );
428 SyckLevel *syck_parser_current_level( SyckParser * );
429 void syck_parser_add_level( SyckParser *, int, enum syck_level_status );
430 void syck_parser_pop_level( SyckParser * );
431 void free_any_io( SyckParser * );
432 long syck_parser_read( SyckParser * );
433 long syck_parser_readlen( SyckParser *, long );
434 SYMID syck_parse( SyckParser * );
435 void syck_default_error_handler( SyckParser *, const char * );
436 SYMID syck_yaml2byte_handler( SyckParser *, SyckNode * );
437 char *syck_yaml2byte( const char * );
438 
439 /*
440  * Allocation prototypes
441  */
442 SyckNode *syck_alloc_map();
443 SyckNode *syck_alloc_seq();
444 SyckNode *syck_alloc_str();
445 void syck_free_node( SyckNode * );
446 void syck_free_members( SyckNode * );
447 SyckNode *syck_new_str( const char *, enum scalar_style );
448 SyckNode *syck_new_str2( const char *, long, enum scalar_style );
449 void syck_replace_str( SyckNode *, const char *, enum scalar_style );
450 void syck_replace_str2( SyckNode *, const char *, long, enum scalar_style );
451 void syck_str_blow_away_commas( SyckNode * );
452 char *syck_str_read( SyckNode * );
453 SyckNode *syck_new_map( SYMID, SYMID );
454 void syck_map_empty( SyckNode * );
455 void syck_map_add( SyckNode *, SYMID, SYMID );
456 SYMID syck_map_read( SyckNode *, enum map_part, long );
457 void syck_map_assign( SyckNode *, enum map_part, long, SYMID );
458 long syck_map_count( SyckNode * );
459 void syck_map_update( SyckNode *, SyckNode * );
460 SyckNode *syck_new_seq( SYMID );
461 void syck_seq_empty( SyckNode * );
462 void syck_seq_add( SyckNode *, SYMID );
463 void syck_seq_assign( SyckNode *, long, SYMID );
464 SYMID syck_seq_read( SyckNode *, long );
465 long syck_seq_count( SyckNode * );
466 
467 /*
468  * Lexer prototypes
469  */
470 void syckerror( void *, const char * );
471 int syckparse( void * );
472 
473 #if defined(__cplusplus)
474 }  /* extern "C" { */
475 #endif
476 
477 #endif /* ifndef SYCK_H */
478