00001 /* 00002 * Copyright 2004 PathScale, Inc. All Rights Reserved. 00003 */ 00004 00005 /* 00006 00007 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00008 00009 This program is free software; you can redistribute it and/or modify it 00010 under the terms of version 2 of the GNU General Public License as 00011 published by the Free Software Foundation. 00012 00013 This program is distributed in the hope that it would be useful, but 00014 WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00016 00017 Further, this software is distributed without any warranty that it is 00018 free of the rightful claim of any third person regarding infringement 00019 or the like. Any license provided herein, whether implied or 00020 otherwise, applies only to this software file. Patent licenses, if 00021 any, provided herein do not apply to combinations of this program with 00022 other software, or any other product whatsoever. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with this program; if not, write the Free Software Foundation, Inc., 59 00026 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00027 00028 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00029 Mountain View, CA 94043, or: 00030 00031 http://www.sgi.com 00032 00033 For further information regarding this notice, see: 00034 00035 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00036 00037 */ 00038 00039 00040 #include <malloc.h> 00041 #include <stdio.h> 00042 #include "option_seen.h" 00043 #include "options.h" 00044 #include "option_names.h" 00045 #include "errors.h" 00046 00047 /* 00048 * option_seen keeps track of whether an option has been seen, 00049 * and the order in which options are seen. 00050 */ 00051 00052 /* 00053 * We have two arrays which point into each other. 00054 * The option_is_seen array has a value for each option flag 00055 * that says whether the option was seen, and if so, points 00056 * into the order_options_seen array. 00057 * The order_options_seen array is an ordered list of options 00058 * that are seen, where the index is the order and the value 00059 * points back to the option_is_seen array. 00060 * In order to allow prepending to the order seen, 00061 * we make the order_options_seen array be a linked list. 00062 */ 00063 typedef struct int_list_rec { 00064 int value; 00065 struct int_list_rec *next; 00066 } int_list, *int_list_p; 00067 typedef struct linked_list_rec { 00068 int_list *head; 00069 int_list *tail; 00070 } linked_list; 00071 static linked_list order_options_seen; 00072 static int_list_p *option_is_seen; 00073 00074 static int_list* IMPLICITLY_SEEN; 00075 #define NOT_SEEN NULL 00076 00077 static int_list* current_seen; /* for iterator */ 00078 00079 /* init the option_seen list */ 00080 void 00081 init_option_seen (void) 00082 { 00083 int i; 00084 option_is_seen = (int_list_p*) malloc(max_options*sizeof(int_list_p)); 00085 for (i = 0; i < max_options; i++) { 00086 option_is_seen[i] = NOT_SEEN; 00087 } 00088 /* make dummy entry for implicitly seen */ 00089 order_options_seen.head = (int_list*)malloc(sizeof(int_list)); 00090 order_options_seen.head->value = -1; 00091 order_options_seen.head->next = NULL; 00092 order_options_seen.tail = order_options_seen.head; 00093 IMPLICITLY_SEEN = order_options_seen.head; 00094 current_seen = 0; /* better not be iterating here */ 00095 } 00096 00097 /* double the number of options available in our structures */ 00098 void 00099 double_max_option_seen (void) 00100 { 00101 /* we assume that max_options var has already been doubled */ 00102 int base; 00103 int i; 00104 int_list_p *new_list = (int_list_p*) realloc ((char*)option_is_seen, 00105 max_options*sizeof(int_list_p)); 00106 if (new_list == NULL) { 00107 internal_error("Out of memory allocating %d options_seen", 00108 max_options); 00109 } 00110 option_is_seen = new_list; 00111 base = max_options/2; 00112 00113 current_seen = 0; /* better not be iterating here */ 00114 for (i = base; i < max_options; i++) { 00115 option_is_seen[i] = NOT_SEEN; 00116 } 00117 } 00118 00119 /* whether option flag was seen or not */ 00120 boolean 00121 option_was_seen (int optflag) 00122 { 00123 return (option_is_seen[optflag] != NOT_SEEN); 00124 } 00125 00126 /* whether option flag was implicitly seen or not */ 00127 boolean 00128 option_was_implicitly_seen (int optflag) 00129 { 00130 return (option_is_seen[optflag] == IMPLICITLY_SEEN); 00131 } 00132 00133 /* set option as seen */ 00134 void 00135 add_option_seen (int optflag) 00136 { 00137 /* create cross-reference between option_is_seen and 00138 * order_options_seen for new option */ 00139 int_list *p; 00140 p = (int_list*)malloc(sizeof(int_list)); 00141 p->value = optflag; 00142 p->next = NULL; 00143 order_options_seen.tail->next = p; 00144 order_options_seen.tail = p; 00145 option_is_seen[optflag] = p; 00146 } 00147 00148 /* set option as seen, add to beginning of ordered list */ 00149 void 00150 prepend_option_seen (int optflag) 00151 { 00152 /* create cross-reference between option_is_seen and 00153 * order_options_seen for new option */ 00154 int_list *p; 00155 p = (int_list*)malloc(sizeof(int_list)); 00156 p->value = optflag; 00157 /* keep implicit option at head, if first option then change tail */ 00158 p->next = order_options_seen.head->next; 00159 order_options_seen.head->next = p; 00160 if (order_options_seen.head == order_options_seen.tail) { 00161 order_options_seen.tail = p; 00162 } 00163 option_is_seen[optflag] = p; 00164 } 00165 00166 /* set option as implicitly seen */ 00167 void 00168 add_option_implicitly_seen (int optflag) 00169 { 00170 /* just mark flag as being implicitly seen; 00171 * don't put in order_option_seen array. */ 00172 option_is_seen[optflag] = IMPLICITLY_SEEN; 00173 } 00174 00175 /* replace old option seen with new value, but in same place */ 00176 void 00177 replace_option_seen (int old_optflag, int new_optflag) 00178 { 00179 int_list* p = option_is_seen[old_optflag]; 00180 option_is_seen[old_optflag] = NOT_SEEN; 00181 option_is_seen[new_optflag] = p; 00182 p->value = new_optflag; 00183 } 00184 00185 static void 00186 delete_order_option (int_list *old) 00187 { 00188 int_list *p; 00189 /* assume that can't remove initial implicit option */ 00190 for (p = order_options_seen.head; p != NULL; p = p->next) { 00191 if (p->next == old) { 00192 /* skip old */ 00193 p->next = old->next; 00194 /* don't set next to NULL, as may need it 00195 * for current_seen */ 00196 /* old->next = NULL; */ 00197 if (p->next == NULL) { 00198 /* must be tail */ 00199 order_options_seen.tail = p; 00200 } 00201 return; 00202 } 00203 } 00204 internal_error("couldn't unset option %d", old->value); 00205 } 00206 00207 /* set option as unseen */ 00208 void 00209 set_option_unseen (int optflag) 00210 { 00211 int_list *p; 00212 p = option_is_seen[optflag]; 00213 option_is_seen[optflag] = NOT_SEEN; 00214 if (p) delete_order_option(p); 00215 } 00216 00217 /* iterator routines, e.g.: 00218 * for (i = first_option_seen(); more_option_seen(); i = next_option_seen()) 00219 */ 00220 00221 int 00222 first_option_seen (void) 00223 { 00224 current_seen = order_options_seen.head->next; /* skip implicit */ 00225 if (current_seen == NULL) { 00226 return 0; 00227 } else { 00228 return current_seen->value; 00229 } 00230 } 00231 00232 int 00233 next_option_seen (void) 00234 { 00235 current_seen = current_seen->next; 00236 if (current_seen == NULL) { 00237 return 0; 00238 } else { 00239 return current_seen->value; 00240 } 00241 } 00242 00243 boolean 00244 more_option_seen (void) 00245 { 00246 return (current_seen != NULL); 00247 } 00248 00249 /* return true if this option was repeated later */ 00250 /* Warning: this routine only works if inside an iterator */ 00251 boolean 00252 current_option_seen_later (int optflag) 00253 { 00254 /* if was seen later, then option_is_seen will point to later use */ 00255 return (current_seen != option_is_seen[optflag]); 00256 } 00257 00258 /* set current option as unseen */ 00259 /* Warning: this routine only works if inside an iterator */ 00260 void 00261 set_current_option_unseen (void) 00262 { 00263 delete_order_option(current_seen); 00264 } 00265 00266 void 00267 dump_option_seen (void) 00268 { 00269 int_list *p; 00270 printf("order_options_seen:\n"); 00271 for (p = order_options_seen.head; p != NULL; p = p->next) { 00272 printf("flag %d\n", p->value); 00273 } 00274 }
1.5.6