coan 4.2.4
if_control.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2004, 2006 Symbian Software Ltd.                        *
00003  *   All rights reserved.                                                  *
00004  *   Copyright (C) 2002, 2003 Tony Finch <dot@dotat.at>.                   *
00005  *   All rights reserved.                                                  *
00006  *   Copyright (C) 1985, 1993 The Regents of the University of California. *
00007  *   All rights reserved.                                                  *
00008  *                                                                         *
00009  *   Contributed by Mike Kinghan, imk@strudl.org, derived from the code    *
00010  *   of Tony Finch                                                         *
00011  *                                                                         *
00012  *   Redistribution and use in source and binary forms, with or without    *
00013  *   modification, are permitted provided that the following conditions    *
00014  *   are met:                                                              *
00015  *                                                                         *
00016  *   Redistributions of source code must retain the above copyright        *
00017  *   notice, this list of conditions and the following disclaimer.         *
00018  *                                                                         *
00019  *   Redistributions in binary form must reproduce the above copyright     *
00020  *   notice, this list of conditions and the following disclaimer in the   *
00021  *   documentation and/or other materials provided with the distribution.  *
00022  *                                                                         *
00023  *   Neither the name of Symbian Software Ltd. nor the names of its        *
00024  *   contributors may be used to endorse or promote products derived from  *
00025  *   this software without specific prior written permission.              *
00026  *                                                                         *
00027  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   *
00028  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     *
00029  *   LIMITED TO, THE IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS    *
00030  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE        *
00031  *   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,   *
00032  *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  *
00033  *   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
00034  *   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    *
00035  *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,*
00036  *   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
00037  *   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH  *
00038  *   DAMAGE.                                                               *
00039  *                                                                         *
00040  **************************************************************************/
00041 
00042 #include "if_control.h"
00043 #include "report.h"
00044 #include "line_edit.h"
00045 #include "line_despatch.h"
00046 #include "chew.h"
00047 #include "io.h"
00048 
00049 
00058 
00062 #define MAXDEPTH        64
00063 
00064 /* Helpers ****************************************************************/
00065 
00067 typedef void transition_t(void);
00068 
00073 static void
00074 done_file(void);
00075 
00077 static void
00078 nest(void);
00079 
00082 static void
00083 set_state(if_state_t is);
00084 
00086 static void Strue (void)
00087 {
00088     drop();
00089     set_state(IF_STATE_TRUE_PREFIX);
00090 }
00092 static void Sfalse(void)
00093 {
00094     drop();
00095     set_state(IF_STATE_FALSE_PREFIX);
00096 }
00098 static void Selse (void)
00099 {
00100     drop();
00101     set_state(IF_STATE_TRUE_ELSE);
00102 }
00104 static void Pelif (void)
00105 {
00106     print();
00107     set_state(IF_STATE_PASS_MIDDLE);
00108 }
00110 static void Pelse (void)
00111 {
00112     print();
00113     set_state(IF_STATE_PASS_ELSE);
00114 }
00116 static void Pendif(void);
00118 static void Dfalse(void)
00119 {
00120     drop();
00121     set_state(IF_STATE_FALSE_TRAILER);
00122 }
00124 static void Delif (void)
00125 {
00126     drop();
00127     set_state(IF_STATE_FALSE_MIDDLE);
00128 }
00130 static void Delse (void)
00131 {
00132     drop();
00133     set_state(IF_STATE_FALSE_ELSE);
00134 }
00136 static void Dendif(void);
00138 static void Fdrop (void)
00139 {
00140     nest();
00141     Dfalse();
00142 }
00144 static void Fpass (void)
00145 {
00146     nest();
00147     Pelif();
00148 }
00150 static void Ftrue (void)
00151 {
00152     nest();
00153     Strue();
00154 }
00156 static void Ffalse(void)
00157 {
00158     nest();
00159     Sfalse();
00160 }
00162 static void Mpass (void)
00163 {
00164     strncpy(GET_PUBLIC(line_edit,keyword), "if  ", 4);
00165     Pelif();
00166 }
00168 static void Mtrue (void)
00169 {
00170     keywordedit("else\n");
00171     set_state(IF_STATE_TRUE_MIDDLE);
00172 }
00174 static void Melif (void)
00175 {
00176     keywordedit("endif\n");
00177     set_state(IF_STATE_FALSE_TRAILER);
00178 }
00180 static void Melse (void)
00181 {
00182     keywordedit("endif\n");
00183     set_state(IF_STATE_FALSE_ELSE);
00184 }
00185 
00190 static transition_t * const
00191 transition_table[IF_STATE_COUNT][LT_SENTINEL] = {
00192     /* IF_STATE_OUTSIDE*/
00193     {
00194         Fpass,
00195         Ftrue,
00196         Ffalse,
00197         orphan_elif,
00198         orphan_elif,
00199         orphan_elif,
00200         orphan_else,
00201         orphan_endif,
00202         print,
00203         done_file
00204     },
00205     /* IF_STATE_FALSE_PREFIX*/
00206     {
00207         Fdrop,
00208         Fdrop,
00209         Fdrop,
00210         Mpass,
00211         Strue,
00212         Sfalse,
00213         Selse,
00214         Dendif,
00215         drop,
00216         early_eof
00217     },
00218     /* IF_STATE_TRUE_PREFIX*/
00219     {
00220         Fpass,
00221         Ftrue,
00222         Ffalse,
00223         Dfalse,
00224         Dfalse,
00225         Dfalse,
00226         Delse,
00227         Dendif,
00228         print,
00229         early_eof
00230     },
00231     /* IF_STATE_PASS_MIDDLE*/
00232     {
00233         Fpass,
00234         Ftrue,
00235         Ffalse,
00236         Pelif,
00237         Mtrue,
00238         Delif,
00239         Pelse,
00240         Pendif,
00241         print,
00242         early_eof
00243     },
00244     /* IF_STATE_FALSE_MIDDLE*/
00245     {
00246         Fdrop,
00247         Fdrop,
00248         Fdrop,
00249         Pelif,
00250         Mtrue,
00251         Delif,
00252         Pelse,
00253         Pendif,
00254         drop,
00255         early_eof
00256     },
00257     /* IF_STATE_TRUE_MIDDLE*/
00258     {
00259         Fpass,
00260         Ftrue,
00261         Ffalse,
00262         Melif,
00263         Melif,
00264         Melif,
00265         Melse,
00266         Pendif,
00267         print,
00268         early_eof
00269     },
00270     /* IF_STATE_PASS_ELSE*/
00271     {
00272         Fpass,
00273         Ftrue,
00274         Ffalse,
00275         orphan_elif,
00276         orphan_elif,
00277         orphan_elif,
00278         orphan_else,
00279         Pendif,
00280         print,
00281         early_eof
00282     },
00283     /* IF_STATE_FALSE_ELSE*/
00284     {
00285         Fdrop,
00286         Fdrop,
00287         Fdrop,
00288         orphan_elif,
00289         orphan_elif,
00290         orphan_elif,
00291         orphan_else,
00292         Dendif,
00293         drop,
00294         early_eof
00295     },
00296     /* IF_STATE_TRUE_ELSE*/
00297     {
00298         Fpass,
00299         Ftrue,
00300         Ffalse,
00301         orphan_elif,
00302         orphan_elif,
00303         orphan_elif,
00304         orphan_else,
00305         Dendif,
00306         print,
00307         early_eof
00308     },
00309     /* IF_STATE_FALSE_TRAILER*/
00310     {
00311         Fdrop,
00312         Fdrop,
00313         Fdrop,
00314         Dfalse,
00315         Dfalse,
00316         Dfalse,
00317         Delse,
00318         Dendif,
00319         drop,
00320         early_eof
00321     }
00322     /*IF     TRUE   FALSE  ELIF   ELTRUE ELFALSE ELSE  ENDIF  PLAIN  EOF*/
00323 };
00324 
00330 
00332 STATE_DEF(if_control)
00333 {
00335     if_state_t  ifstate[MAXDEPTH];
00337     size_t              depth;
00339     size_t              if_start_lines[MAXDEPTH];
00340 }
00341 STATE_T(if_control);
00342 
00347 
00348 NO_PUBLIC_STATE(if_control);
00349 
00350 IMPLEMENT(if_control,ZERO_INITABLE);
00351 
00354 static void
00355 done_file(void)
00356 {
00357     if (GET_PUBLIC(chew,comment_state) != NO_COMMENT) {
00358         parse_error(GRIPE_EOF_IN_COMMENT,
00359                     "EOF in comment, #error ... or #define ... commencing line %d",
00360                     GET_PUBLIC(chew,last_comment_start_line));
00361     }
00362     if (GET_PUBLIC(chew,in_double_quote)) {
00363         parse_error(GRIPE_EOF_IN_QUOTE,
00364                     "EOF in quotation commencing line %d",
00365                     GET_PUBLIC(chew,last_quote_start_line));
00366     }
00367 }
00368 
00369 static void
00370 nest(void)
00371 {
00372     size_t deep = ++SET_STATE(if_control,depth);
00373     if (deep >= MAXDEPTH) {
00374         bail(GRIPE_TOO_DEEP,"Too many levels of nesting");
00375     }
00376     GET_STATE(if_control,if_start_lines)[deep] = GET_PUBLIC(io,line_num);
00377 }
00378 
00379 static void
00380 set_state(if_state_t is)
00381 {
00382     size_t deep = if_depth();
00383     GET_STATE(if_control,ifstate)[deep] = is;
00384 }
00385 
00386 static void Pendif(void)
00387 {
00388     print();
00389     --SET_STATE(if_control,depth);
00390 }
00391 
00392 static void Dendif(void)
00393 {
00394     drop();
00395     --SET_STATE(if_control,depth);
00396 }
00397 
00398 /* API ********************************************************************/
00399 
00400 void
00401 transition(line_type_t linetype)
00402 {
00403     if_state_t state = GET_STATE(if_control,ifstate)[if_depth()];
00404     transition_table[state][linetype]();
00405 }
00406 
00407 bool
00408 dead_line(void)
00409 {
00410     if_state_t state =
00411         GET_STATE(if_control,ifstate)[if_depth()];
00412     return state == IF_STATE_FALSE_PREFIX ||
00413            state == IF_STATE_FALSE_MIDDLE ||
00414            state == IF_STATE_FALSE_ELSE ||
00415            state == IF_STATE_FALSE_TRAILER;
00416 }
00417 
00418 bool
00419 was_unconditional_line(void)
00420 {
00421     return
00422         GET_STATE(if_control,ifstate)[if_depth()] ==
00423         IF_STATE_OUTSIDE;
00424 }
00425 
00426 bool
00427 is_unconditional_line(void)
00428 {
00429     if_state_t state =
00430         GET_STATE(if_control,ifstate)[if_depth()];
00431     return      state == IF_STATE_OUTSIDE ||
00432             state == IF_STATE_TRUE_PREFIX ||
00433             state == IF_STATE_TRUE_MIDDLE ||
00434             state == IF_STATE_TRUE_ELSE ;
00435 }
00436 
00437 if_state_t
00438 if_state(void)
00439 {
00440     return GET_STATE(if_control,ifstate)[if_depth()];
00441 }
00442 
00443 size_t
00444 if_depth(void)
00445 {
00446     return GET_STATE(if_control,depth);
00447 }
00448 
00449 size_t
00450 if_start_line(void)
00451 {
00452     return GET_STATE(if_control,if_start_lines)[if_depth()];
00453 }
00454 
00455 void
00456 if_control_toplevel(void)
00457 {
00458     SET_STATE(if_control,depth) = 0;
00459 }
00460 
00461 
00462 /* EOF*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines