listing.c revision 34345a63
1/************************************************************ 2 Copyright 1996 by Silicon Graphics Computer Systems, Inc. 3 4 Permission to use, copy, modify, and distribute this 5 software and its documentation for any purpose and without 6 fee is hereby granted, provided that the above copyright 7 notice appear in all copies and that both that copyright 8 notice and this permission notice appear in supporting 9 documentation, and that the name of Silicon Graphics not be 10 used in advertising or publicity pertaining to distribution 11 of the software without specific prior written permission. 12 Silicon Graphics makes no representation about the suitability 13 of this software for any purpose. It is provided "as is" 14 without any express or implied warranty. 15 16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25 ********************************************************/ 26/*********************************************************** 27 28Copyright 1988, 1998 The Open Group 29 30Permission to use, copy, modify, distribute, and sell this software and its 31documentation for any purpose is hereby granted without fee, provided that 32the above copyright notice appear in all copies and that both that 33copyright notice and this permission notice appear in supporting 34documentation. 35 36The above copyright notice and this permission notice shall be included in 37all copies or substantial portions of the Software. 38 39THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 43AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 44CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 45 46Except as contained in this notice, the name of The Open Group shall not be 47used in advertising or otherwise to promote the sale, use or other dealings 48in this Software without prior written authorization from The Open Group. 49 50 51Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 52 53 All Rights Reserved 54 55Permission to use, copy, modify, and distribute this software and its 56documentation for any purpose and without fee is hereby granted, 57provided that the above copyright notice appear in all copies and that 58both that copyright notice and this permission notice appear in 59supporting documentation, and that the name of Digital not be 60used in advertising or publicity pertaining to distribution of the 61software without specific, written prior permission. 62 63DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 64ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 65DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 66ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 67WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 68ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 69SOFTWARE. 70 71******************************************************************/ 72 73#include <stdio.h> 74#include <ctype.h> 75#include <sys/types.h> 76#include <sys/stat.h> 77#include <X11/keysym.h> 78 79#if defined(sgi) 80#include <malloc.h> 81#endif 82 83#define DEBUG_VAR listingDebug 84#include "xkbcomp.h" 85#include <stdlib.h> 86 87#ifdef _POSIX_SOURCE 88# include <limits.h> 89#else 90# define _POSIX_SOURCE 91# include <limits.h> 92# undef _POSIX_SOURCE 93#endif 94 95#ifndef PATH_MAX 96#ifdef WIN32 97#define PATH_MAX 512 98#else 99#include <sys/param.h> 100#endif 101#ifndef PATH_MAX 102#ifdef MAXPATHLEN 103#define PATH_MAX MAXPATHLEN 104#else 105#define PATH_MAX 1024 106#endif 107#endif 108#endif 109 110#ifdef WIN32 111# include <windows.h> 112# define FileName(file) file.cFileName 113# undef TEXT 114# undef ALTERNATE 115#else 116# include <dirent.h> 117# define FileName(file) file->d_name 118#endif 119 120#include "xkbpath.h" 121#include "parseutils.h" 122#include "misc.h" 123#include "tokens.h" 124#include <X11/extensions/XKBgeom.h> 125 126#define lowbit(x) ((x) & (-(x))) 127 128unsigned int listingDebug; 129 130static int szListing = 0; 131static int nListed = 0; 132static int nFilesListed = 0; 133 134typedef struct _Listing 135{ 136 char *file; 137 char *map; 138} Listing; 139 140static int szMapOnly; 141static int nMapOnly; 142static char **mapOnly; 143 144static Listing *list = NULL; 145 146/***====================================================================***/ 147 148int 149AddMapOnly(char *map) 150{ 151 if (nMapOnly >= szMapOnly) 152 { 153 if (szMapOnly < 1) 154 szMapOnly = 5; 155 else 156 szMapOnly *= 2; 157 mapOnly = uTypedRealloc(list, szMapOnly, char *); 158 if (!mapOnly) 159 { 160 WSGO("Couldn't allocate list of maps\n"); 161 return 0; 162 } 163 } 164 mapOnly[nMapOnly++] = map; 165 return 1; 166} 167 168int 169AddListing(char *file, char *map) 170{ 171 if (nListed >= szListing) 172 { 173 if (szListing < 1) 174 szListing = 10; 175 else 176 szListing *= 2; 177 list = uTypedRealloc(list, szListing, Listing); 178 if (!list) 179 { 180 WSGO("Couldn't allocate list of files and maps\n"); 181 ACTION("Exiting\n"); 182 exit(1); 183 } 184 } 185 186 list[nListed].file = file; 187 list[nListed].map = map; 188 nListed++; 189 if (file != NULL) 190 nFilesListed++; 191 return 1; 192} 193 194/***====================================================================***/ 195 196static void 197ListFile(FILE * outFile, char *fileName, XkbFile * map) 198{ 199 register unsigned flags; 200 char *mapName; 201 202 flags = map->flags; 203 if ((flags & XkbLC_Hidden) && (!(verboseLevel & WantHiddenMaps))) 204 return; 205 if ((flags & XkbLC_Partial) && (!(verboseLevel & WantPartialMaps))) 206 return; 207 if (verboseLevel & WantLongListing) 208 { 209 fprintf(outFile, (flags & XkbLC_Hidden) ? "h" : "-"); 210 fprintf(outFile, (flags & XkbLC_Default) ? "d" : "-"); 211 fprintf(outFile, (flags & XkbLC_Partial) ? "p" : "-"); 212 fprintf(outFile, "----- "); 213 if (map->type == XkmSymbolsIndex) 214 { 215 fprintf(outFile, (flags & XkbLC_AlphanumericKeys) ? "a" : "-"); 216 fprintf(outFile, (flags & XkbLC_ModifierKeys) ? "m" : "-"); 217 fprintf(outFile, (flags & XkbLC_KeypadKeys) ? "k" : "-"); 218 fprintf(outFile, (flags & XkbLC_FunctionKeys) ? "f" : "-"); 219 fprintf(outFile, (flags & XkbLC_AlternateGroup) ? "g" : "-"); 220 fprintf(outFile, "--- "); 221 } 222 else 223 fprintf(outFile, "-------- "); 224 } 225 mapName = map->name; 226 if ((!(verboseLevel & WantFullNames)) && ((flags & XkbLC_Default) != 0)) 227 mapName = NULL; 228 if (dirsToStrip > 0) 229 { 230 char *tmp, *last; 231 int i; 232 for (i = 0, tmp = last = fileName; (i < dirsToStrip) && tmp; i++) 233 { 234 last = tmp; 235 tmp = strchr(tmp, '/'); 236 if (tmp != NULL) 237 tmp++; 238 } 239 fileName = (tmp ? tmp : last); 240 } 241 if (mapName) 242 fprintf(outFile, "%s(%s)\n", fileName, mapName); 243 else 244 fprintf(outFile, "%s\n", fileName); 245 return; 246} 247 248/***====================================================================***/ 249 250static int 251AddDirectory(char *head, char *ptrn, char *rest, char *map) 252{ 253#ifdef WIN32 254 HANDLE dirh; 255 WIN32_FIND_DATA file; 256#else 257 DIR *dirp; 258 struct dirent *file; 259#endif 260 int nMatch; 261 262 if (map == NULL) 263 { 264 char *tmp = ptrn; 265 if ((rest == NULL) && (ptrn != NULL) && (strchr(ptrn, '/') == NULL)) 266 { 267 tmp = ptrn; 268 map = strchr(ptrn, '('); 269 } 270 else if ((rest == NULL) && (ptrn == NULL) && 271 (head != NULL) && (strchr(head, '/') == NULL)) 272 { 273 tmp = head; 274 map = strchr(head, '('); 275 } 276 if (map != NULL) 277 { 278 tmp = strchr(tmp, ')'); 279 if ((tmp == NULL) || (tmp[1] != '\0')) 280 { 281 ERROR1("File and map must have the format file(map)\n"); 282 return 0; 283 } 284 *map = '\0'; 285 map++; 286 *tmp = '\0'; 287 } 288 } 289#ifdef WIN32 290 if ((dirh = FindFirstFile("*.*", &file)) == INVALID_HANDLE_VALUE) 291 return 0; 292#else 293 if ((dirp = opendir((head ? head : "."))) == NULL) 294 return 0; 295 nMatch = 0; 296#endif 297#ifdef WIN32 298 do 299#else 300 while ((file = readdir(dirp)) != NULL) 301#endif 302 { 303 char *tmp, *filename; 304 struct stat sbuf; 305 306 filename = FileName(file); 307 if (!filename || filename[0] == '.') 308 continue; 309 if (ptrn && (!XkbNameMatchesPattern(filename, ptrn))) 310 continue; 311 tmp = 312 (char *) uAlloc((head ? strlen(head) : 0) + strlen(filename) + 2); 313 if (!tmp) 314 continue; 315 sprintf(tmp, "%s%s%s", (head ? head : ""), (head ? "/" : ""), 316 filename); 317 if (stat(tmp, &sbuf) < 0) 318 { 319 uFree(tmp); 320 continue; 321 } 322 if (((rest != NULL) && (!S_ISDIR(sbuf.st_mode))) || 323 ((map != NULL) && (S_ISDIR(sbuf.st_mode)))) 324 { 325 uFree(tmp); 326 continue; 327 } 328 if (S_ISDIR(sbuf.st_mode)) 329 { 330 if ((rest != NULL) || (verboseLevel & ListRecursive)) 331 nMatch += AddDirectory(tmp, rest, NULL, map); 332 } 333 else 334 nMatch += AddListing(tmp, map); 335 } 336#ifdef WIN32 337 while (FindNextFile(dirh, &file)); 338#endif 339 return nMatch; 340} 341 342/***====================================================================***/ 343 344Bool 345AddMatchingFiles(char *head_in) 346{ 347 char *str, *head, *ptrn, *rest = NULL; 348 349 if (head_in == NULL) 350 return 0; 351 ptrn = NULL; 352 for (str = head_in; (*str != '\0') && (*str != '?') && (*str != '*'); 353 str++) 354 { 355 if ((str != head_in) && (*str == '/')) 356 ptrn = str; 357 } 358 if (*str == '\0') 359 { /* no wildcards */ 360 head = head_in; 361 ptrn = NULL; 362 rest = NULL; 363 } 364 else if (ptrn == NULL) 365 { /* no slash before the first wildcard */ 366 head = NULL; 367 ptrn = head_in; 368 } 369 else 370 { /* slash followed by wildcard */ 371 head = head_in; 372 *ptrn = '\0'; 373 ptrn++; 374 } 375 if (ptrn) 376 { 377 rest = strchr(ptrn, '/'); 378 if (rest != NULL) 379 { 380 *rest = '\0'; 381 rest++; 382 } 383 } 384 if (((rest && ptrn) 385 && ((strchr(ptrn, '(') != NULL) || (strchr(ptrn, ')') != NULL))) 386 || (head 387 && ((strchr(head, '(') != NULL) || (strchr(head, ')') != NULL)))) 388 { 389 ERROR1("Files/maps to list must have the form file(map)\n"); 390 ACTION("Illegal specifier ignored\n"); 391 return 0; 392 } 393 return AddDirectory(head, ptrn, rest, NULL); 394} 395 396/***====================================================================***/ 397 398static Bool 399MapMatches(char *mapToConsider, char *ptrn) 400{ 401 int i; 402 403 if (ptrn != NULL) 404 return XkbNameMatchesPattern(mapToConsider, ptrn); 405 if (nMapOnly < 1) 406 return True; 407 for (i = 0; i < nMapOnly; i++) 408 { 409 if (XkbNameMatchesPattern(mapToConsider, mapOnly[i])) 410 return True; 411 } 412 return False; 413} 414 415int 416GenerateListing(char *out_name) 417{ 418 int i; 419 FILE *inputFile, *outFile; 420 XkbFile *rtrn, *mapToUse; 421 unsigned oldWarningLevel; 422 char *mapName; 423 424 if (nFilesListed < 1) 425 { 426 ERROR1("Must specify at least one file or pattern to list\n"); 427 return 0; 428 } 429 if ((!out_name) || ((out_name[0] == '-') && (out_name[1] == '\0'))) 430 outFile = stdout; 431 else if ((outFile = fopen(out_name, "w")) == NULL) 432 { 433 ERROR1("Cannot open \"%s\" to write keyboard description\n", 434 out_name); 435 ACTION("Exiting\n"); 436 return 0; 437 } 438#ifdef DEBUG 439 if (warningLevel > 9) 440 fprintf(stderr, "should list:\n"); 441#endif 442 for (i = 0; i < nListed; i++) 443 { 444#ifdef DEBUG 445 if (warningLevel > 9) 446 { 447 fprintf(stderr, "%s(%s)\n", 448 (list[i].file ? list[i].file : "*"), 449 (list[i].map ? list[i].map : "*")); 450 } 451#endif 452 oldWarningLevel = warningLevel; 453 warningLevel = 0; 454 if (list[i].file) 455 { 456 struct stat sbuf; 457 458 if (stat(list[i].file, &sbuf) < 0) 459 { 460 if (oldWarningLevel > 5) 461 WARN1("Couldn't open \"%s\"\n", list[i].file); 462 continue; 463 } 464 if (S_ISDIR(sbuf.st_mode)) 465 { 466 if (verboseLevel & ListRecursive) 467 AddDirectory(list[i].file, NULL, NULL, NULL); 468 continue; 469 } 470 471 inputFile = fopen(list[i].file, "r"); 472 if (!inputFile) 473 { 474 if (oldWarningLevel > 5) 475 WARN1("Couldn't open \"%s\"\n", list[i].file); 476 continue; 477 } 478 setScanState(list[i].file, 1); 479 if (XKBParseFile(inputFile, &rtrn) && (rtrn != NULL)) 480 { 481 mapName = list[i].map; 482 mapToUse = rtrn; 483 for (; mapToUse; mapToUse = (XkbFile *) mapToUse->common.next) 484 { 485 if (!MapMatches(mapToUse->name, mapName)) 486 continue; 487 ListFile(outFile, list[i].file, mapToUse); 488 } 489 } 490 fclose(inputFile); 491 } 492 warningLevel = oldWarningLevel; 493 } 494 return 1; 495} 496