1 /*
2  * Copyright 1993, 2000 Christopher Seiwald.
3  *
4  * This file is part of Jam - see jam.c for Copyright information.
5  */
6 
7 /*  This file is ALSO:
8  *  Copyright 2001-2004 David Abrahams.
9  *  Distributed under the Boost Software License, Version 1.0.
10  *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
11  */
12 
13 #include "jam.h"
14 #include "lists.h"
15 #include "parse.h"
16 #include "scan.h"
17 #include "object.h"
18 #include "modules.h"
19 #include "frames.h"
20 #include "function.h"
21 
22 /*
23  * parse.c - make and destroy parse trees as driven by the parser
24  *
25  * 09/07/00 (seiwald) - ref count on PARSE to avoid freeing when used,
26  *      as per Matt Armstrong.
27  * 09/11/00 (seiwald) - structure reworked to reflect that (*func)()
28  *      returns a LIST *.
29  */
30 
31 static PARSE * yypsave;
32 
parse_impl(FRAME * frame)33 static void parse_impl( FRAME * frame )
34 {
35 
36     /* Now parse each block of rules and execute it. Execute it outside of the
37      * parser so that recursive calls to yyrun() work (no recursive yyparse's).
38      */
39 
40     for ( ; ; )
41     {
42         PARSE * p;
43         FUNCTION * func;
44 
45         /* Filled by yyparse() calling parse_save(). */
46         yypsave = 0;
47 
48         /* If parse error or empty parse, outta here. */
49         if ( yyparse() || !( p = yypsave ) )
50             break;
51 
52         /* Run the parse tree. */
53         func = function_compile( p );
54         parse_free( p );
55         list_free( function_run( func, frame, stack_global() ) );
56         function_free( func );
57     }
58 
59     yyfdone();
60 }
61 
62 
parse_file(OBJECT * f,FRAME * frame)63 void parse_file( OBJECT * f, FRAME * frame )
64 {
65     /* Suspend scan of current file and push this new file in the stream. */
66     yyfparse( f );
67 
68     parse_impl( frame );
69 }
70 
71 
parse_string(OBJECT * name,const char ** lines,FRAME * frame)72 void parse_string( OBJECT * name, const char * * lines, FRAME * frame )
73 {
74     yysparse( name, lines );
75     parse_impl( frame );
76 }
77 
78 
parse_save(PARSE * p)79 void parse_save( PARSE * p )
80 {
81     yypsave = p;
82 }
83 
84 
parse_make(int type,PARSE * left,PARSE * right,PARSE * third,OBJECT * string,OBJECT * string1,int num)85 PARSE * parse_make(
86     int      type,
87     PARSE  * left,
88     PARSE  * right,
89     PARSE  * third,
90     OBJECT * string,
91     OBJECT * string1,
92     int      num )
93 {
94     PARSE * p = (PARSE *)BJAM_MALLOC( sizeof( PARSE ) );
95 
96     p->type = type;
97     p->left = left;
98     p->right = right;
99     p->third = third;
100     p->string = string;
101     p->string1 = string1;
102     p->num = num;
103     p->refs = 1;
104     p->rulename = 0;
105 
106     if ( left )
107     {
108         p->file = object_copy( left->file );
109         p->line = left->line;
110     }
111     else
112     {
113         yyinput_last_read_token( &p->file, &p->line );
114         p->file = object_copy( p->file );
115     }
116 
117     return p;
118 }
119 
120 
parse_refer(PARSE * p)121 void parse_refer( PARSE * p )
122 {
123     ++p->refs;
124 }
125 
126 
parse_free(PARSE * p)127 void parse_free( PARSE * p )
128 {
129     if ( --p->refs )
130         return;
131 
132     if ( p->string )
133         object_free( p->string );
134     if ( p->string1 )
135         object_free( p->string1 );
136     if ( p->left )
137         parse_free( p->left );
138     if ( p->right )
139         parse_free( p->right );
140     if ( p->third )
141         parse_free( p->third );
142     if ( p->rulename )
143         object_free( p->rulename );
144     if ( p->file )
145         object_free( p->file );
146 
147     BJAM_FREE( (char *)p );
148 }
149