tabs.c (262629) | tabs.c (262685) |
---|---|
1/**************************************************************************** | 1/**************************************************************************** |
2 * Copyright (c) 2008-2009,2010 Free Software Foundation, Inc. * | 2 * Copyright (c) 2008-2012,2013 Free Software Foundation, Inc. * |
3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * --- 21 unchanged lines hidden (view full) --- 32 33/* 34 * tabs.c -- set terminal hard-tabstops 35 */ 36 37#define USE_LIBTINFO 38#include <progs.priv.h> 39 | 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * --- 21 unchanged lines hidden (view full) --- 32 33/* 34 * tabs.c -- set terminal hard-tabstops 35 */ 36 37#define USE_LIBTINFO 38#include <progs.priv.h> 39 |
40MODULE_ID("$Id: tabs.c,v 1.19 2010/10/23 22:26:01 tom Exp $") | 40MODULE_ID("$Id: tabs.c,v 1.34 2013/06/11 08:18:27 tom Exp $") |
41 42static void usage(void) GCC_NORETURN; 43 | 41 42static void usage(void) GCC_NORETURN; 43 |
44static char *prg_name; |
|
44static int max_cols; 45 | 45static int max_cols; 46 |
47static void 48failed(const char *s) 49{ 50 perror(s); 51 ExitProgram(EXIT_FAILURE); 52} 53 |
|
46static int 47putch(int c) 48{ 49 return putchar(c); 50} 51 52static void 53do_tabs(int *tab_list) --- 24 unchanged lines hidden (view full) --- 78decode_tabs(const char *tab_list) 79{ 80 int *result = typeCalloc(int, strlen(tab_list) + (unsigned) max_cols); 81 int n = 0; 82 int value = 0; 83 int prior = 0; 84 int ch; 85 | 54static int 55putch(int c) 56{ 57 return putchar(c); 58} 59 60static void 61do_tabs(int *tab_list) --- 24 unchanged lines hidden (view full) --- 86decode_tabs(const char *tab_list) 87{ 88 int *result = typeCalloc(int, strlen(tab_list) + (unsigned) max_cols); 89 int n = 0; 90 int value = 0; 91 int prior = 0; 92 int ch; 93 |
86 if (result != 0) { 87 while ((ch = *tab_list++) != '\0') { 88 if (isdigit(UChar(ch))) { 89 value *= 10; 90 value += (ch - '0'); 91 } else if (ch == ',') { 92 result[n] = value + prior; 93 if (n > 0 && result[n] <= result[n - 1]) { 94 fprintf(stderr, 95 "tab-stops are not in increasing order: %d %d\n", 96 value, result[n - 1]); 97 free(result); 98 result = 0; 99 break; 100 } 101 ++n; 102 value = 0; 103 prior = 0; 104 } else if (ch == '+') { 105 if (n) 106 prior = result[n - 1]; | 94 if (result == 0) 95 failed("decode_tabs"); 96 97 while ((ch = *tab_list++) != '\0') { 98 if (isdigit(UChar(ch))) { 99 value *= 10; 100 value += (ch - '0'); 101 } else if (ch == ',') { 102 result[n] = value + prior; 103 if (n > 0 && result[n] <= result[n - 1]) { 104 fprintf(stderr, 105 "%s: tab-stops are not in increasing order: %d %d\n", 106 prg_name, value, result[n - 1]); 107 free(result); 108 result = 0; 109 break; |
107 } | 110 } |
111 ++n; 112 value = 0; 113 prior = 0; 114 } else if (ch == '+') { 115 if (n) 116 prior = result[n - 1]; |
|
108 } 109 } 110 111 if (result != 0) { 112 /* 113 * If there is only one value, then it is an option such as "-8". 114 */ 115 if ((n == 0) && (value > 0)) { 116 int step = value; | 117 } 118 } 119 120 if (result != 0) { 121 /* 122 * If there is only one value, then it is an option such as "-8". 123 */ 124 if ((n == 0) && (value > 0)) { 125 int step = value; |
126 value = 1; |
|
117 while (n < max_cols - 1) { 118 result[n++] = value; 119 value += step; 120 } 121 } 122 123 /* 124 * Add the last value, if any. 125 */ 126 result[n++] = value + prior; 127 result[n] = 0; 128 } | 127 while (n < max_cols - 1) { 128 result[n++] = value; 129 value += step; 130 } 131 } 132 133 /* 134 * Add the last value, if any. 135 */ 136 result[n++] = value + prior; 137 result[n] = 0; 138 } |
139 |
|
129 return result; 130} 131 132static void 133print_ruler(int *tab_list) 134{ 135 int last = 0; 136 int stop; 137 int n; 138 139 /* first print a readable ruler */ 140 for (n = 0; n < max_cols; n += 10) { 141 int ch = 1 + (n / 10); 142 char buffer[20]; | 140 return result; 141} 142 143static void 144print_ruler(int *tab_list) 145{ 146 int last = 0; 147 int stop; 148 int n; 149 150 /* first print a readable ruler */ 151 for (n = 0; n < max_cols; n += 10) { 152 int ch = 1 + (n / 10); 153 char buffer[20]; |
143 sprintf(buffer, "----+----%c", 144 ((ch < 10) 145 ? (ch + '0') 146 : (ch + 'A' - 10))); | 154 _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) 155 "----+----%c", 156 ((ch < 10) 157 ? (ch + '0') 158 : (ch + 'A' - 10))); |
147 printf("%.*s", ((max_cols - n) > 10) ? 10 : (max_cols - n), buffer); 148 } 149 putchar('\n'); 150 151 /* now, print '*' for each stop */ 152 for (n = 0, last = 0; (tab_list[n] > 0) && (last < max_cols); ++n) { 153 stop = tab_list[n]; 154 while (++last < stop) { --- 67 unchanged lines hidden (view full) --- 222} 223 224static bool 225comma_is_needed(const char *source) 226{ 227 bool result = FALSE; 228 229 if (source != 0) { | 159 printf("%.*s", ((max_cols - n) > 10) ? 10 : (max_cols - n), buffer); 160 } 161 putchar('\n'); 162 163 /* now, print '*' for each stop */ 164 for (n = 0, last = 0; (tab_list[n] > 0) && (last < max_cols); ++n) { 165 stop = tab_list[n]; 166 while (++last < stop) { --- 67 unchanged lines hidden (view full) --- 234} 235 236static bool 237comma_is_needed(const char *source) 238{ 239 bool result = FALSE; 240 241 if (source != 0) { |
230 unsigned len = strlen(source); | 242 size_t len = strlen(source); |
231 if (len != 0) 232 result = (source[len - 1] != ','); 233 } else { 234 result = FALSE; 235 } 236 return result; 237} 238 --- 7 unchanged lines hidden (view full) --- 246static const char * 247add_to_tab_list(char **append, const char *value) 248{ 249 char *result = *append; 250 char *copied = trimmed_tab_list(value); 251 252 if (copied != 0 && *copied != '\0') { 253 const char *comma = ","; | 243 if (len != 0) 244 result = (source[len - 1] != ','); 245 } else { 246 result = FALSE; 247 } 248 return result; 249} 250 --- 7 unchanged lines hidden (view full) --- 258static const char * 259add_to_tab_list(char **append, const char *value) 260{ 261 char *result = *append; 262 char *copied = trimmed_tab_list(value); 263 264 if (copied != 0 && *copied != '\0') { 265 const char *comma = ","; |
254 unsigned need = 1 + strlen(copied); | 266 size_t need = 1 + strlen(copied); |
255 256 if (*copied == ',') 257 comma = ""; 258 else if (!comma_is_needed(*append)) 259 comma = ""; 260 261 need += strlen(comma); 262 if (*append != 0) 263 need += strlen(*append); 264 265 result = malloc(need); | 267 268 if (*copied == ',') 269 comma = ""; 270 else if (!comma_is_needed(*append)) 271 comma = ""; 272 273 need += strlen(comma); 274 if (*append != 0) 275 need += strlen(*append); 276 277 result = malloc(need); |
266 if (result != 0) { 267 *result = '\0'; 268 if (*append != 0) { 269 strcpy(result, *append); 270 free(*append); 271 } 272 strcat(result, comma); 273 strcat(result, copied); | 278 if (result == 0) 279 failed("add_to_tab_list"); 280 281 *result = '\0'; 282 if (*append != 0) { 283 _nc_STRCPY(result, *append, need); 284 free(*append); |
274 } | 285 } |
286 _nc_STRCAT(result, comma, need); 287 _nc_STRCAT(result, copied, need); |
|
275 276 *append = result; 277 } 278 return result; 279} 280 281/* 282 * Check for illegal characters in the tab-list. 283 */ 284static bool | 288 289 *append = result; 290 } 291 return result; 292} 293 294/* 295 * Check for illegal characters in the tab-list. 296 */ 297static bool |
285legal_tab_list(const char *program, const char *tab_list) | 298legal_tab_list(const char *tab_list) |
286{ 287 bool result = TRUE; 288 289 if (tab_list != 0 && *tab_list != '\0') { 290 if (comma_is_needed(tab_list)) { 291 int n, ch; 292 for (n = 0; tab_list[n] != '\0'; ++n) { 293 ch = UChar(tab_list[n]); 294 if (!(isdigit(ch) || ch == ',' || ch == '+')) { 295 fprintf(stderr, 296 "%s: unexpected character found '%c'\n", | 299{ 300 bool result = TRUE; 301 302 if (tab_list != 0 && *tab_list != '\0') { 303 if (comma_is_needed(tab_list)) { 304 int n, ch; 305 for (n = 0; tab_list[n] != '\0'; ++n) { 306 ch = UChar(tab_list[n]); 307 if (!(isdigit(ch) || ch == ',' || ch == '+')) { 308 fprintf(stderr, 309 "%s: unexpected character found '%c'\n", |
297 program, ch); | 310 prg_name, ch); |
298 result = FALSE; 299 break; 300 } 301 } 302 } else { | 311 result = FALSE; 312 break; 313 } 314 } 315 } else { |
303 fprintf(stderr, "%s: trailing comma found '%s'\n", program, tab_list); | 316 fprintf(stderr, "%s: trailing comma found '%s'\n", prg_name, tab_list); |
304 result = FALSE; 305 } 306 } else { | 317 result = FALSE; 318 } 319 } else { |
307 fprintf(stderr, "%s: no tab-list given\n", program); | 320 fprintf(stderr, "%s: no tab-list given\n", prg_name); |
308 result = FALSE; 309 } 310 return result; 311} 312 | 321 result = FALSE; 322 } 323 return result; 324} 325 |
326static char * 327skip_list(char *value) 328{ 329 while (*value != '\0' && 330 (isdigit(UChar(*value)) || 331 isspace(UChar(*value)) || 332 strchr("+,", UChar(*value)) != 0)) { 333 ++value; 334 } 335 return value; 336} 337 |
|
313static void 314usage(void) 315{ 316 static const char *msg[] = 317 { 318 "Usage: tabs [options] [tabstop-list]" 319 ,"" 320 ,"Options:" --- 6 unchanged lines hidden (view full) --- 327 ," -c3 COBOL compact format extended" 328 ," -d debug (show ruler with expected/actual tab positions)" 329 ," -f FORTRAN" 330 ," -n no-op (do not modify terminal settings)" 331 ," -p PL/I" 332 ," -s SNOBOL" 333 ," -u UNIVAC 1100 Assembler" 334 ," -T name use terminal type 'name'" | 338static void 339usage(void) 340{ 341 static const char *msg[] = 342 { 343 "Usage: tabs [options] [tabstop-list]" 344 ,"" 345 ,"Options:" --- 6 unchanged lines hidden (view full) --- 352 ," -c3 COBOL compact format extended" 353 ," -d debug (show ruler with expected/actual tab positions)" 354 ," -f FORTRAN" 355 ," -n no-op (do not modify terminal settings)" 356 ," -p PL/I" 357 ," -s SNOBOL" 358 ," -u UNIVAC 1100 Assembler" 359 ," -T name use terminal type 'name'" |
360 ," -V print version" |
|
335 ,"" 336 ,"A tabstop-list is an ordered list of column numbers, e.g., 1,11,21" 337 ,"or 1,+10,+10 which is the same." 338 }; 339 unsigned n; 340 341 fflush(stdout); 342 for (n = 0; n < SIZEOF(msg); ++n) { --- 5 unchanged lines hidden (view full) --- 348int 349main(int argc, char *argv[]) 350{ 351 int rc = EXIT_FAILURE; 352 bool debug = FALSE; 353 bool no_op = FALSE; 354 int n, ch; 355 NCURSES_CONST char *term_name = 0; | 361 ,"" 362 ,"A tabstop-list is an ordered list of column numbers, e.g., 1,11,21" 363 ,"or 1,+10,+10 which is the same." 364 }; 365 unsigned n; 366 367 fflush(stdout); 368 for (n = 0; n < SIZEOF(msg); ++n) { --- 5 unchanged lines hidden (view full) --- 374int 375main(int argc, char *argv[]) 376{ 377 int rc = EXIT_FAILURE; 378 bool debug = FALSE; 379 bool no_op = FALSE; 380 int n, ch; 381 NCURSES_CONST char *term_name = 0; |
356 const char *mar_list = 0; /* ignored */ | |
357 char *append = 0; 358 const char *tab_list = 0; 359 | 382 char *append = 0; 383 const char *tab_list = 0; 384 |
385 prg_name = _nc_rootname(argv[0]); 386 |
|
360 if ((term_name = getenv("TERM")) == 0) 361 term_name = "ansi+tabs"; 362 363 /* cannot use getopt, since some options are two-character */ 364 for (n = 1; n < argc; ++n) { 365 char *option = argv[n]; 366 switch (option[0]) { 367 case '-': 368 while ((ch = *++option) != '\0') { 369 switch (ch) { 370 case 'a': | 387 if ((term_name = getenv("TERM")) == 0) 388 term_name = "ansi+tabs"; 389 390 /* cannot use getopt, since some options are two-character */ 391 for (n = 1; n < argc; ++n) { 392 char *option = argv[n]; 393 switch (option[0]) { 394 case '-': 395 while ((ch = *++option) != '\0') { 396 switch (ch) { 397 case 'a': |
371 switch (*option) { | 398 switch (*++option) { 399 default: |
372 case '\0': 373 tab_list = "1,10,16,36,72"; | 400 case '\0': 401 tab_list = "1,10,16,36,72"; |
402 option--; |
|
374 /* Assembler, IBM S/370, first format */ 375 break; 376 case '2': 377 tab_list = "1,10,16,40,72"; 378 /* Assembler, IBM S/370, second format */ 379 break; | 403 /* Assembler, IBM S/370, first format */ 404 break; 405 case '2': 406 tab_list = "1,10,16,40,72"; 407 /* Assembler, IBM S/370, second format */ 408 break; |
380 default: 381 usage(); | |
382 } 383 break; 384 case 'c': | 409 } 410 break; 411 case 'c': |
385 switch (*option) { | 412 switch (*++option) { 413 default: |
386 case '\0': 387 tab_list = "1,8,12,16,20,55"; | 414 case '\0': 415 tab_list = "1,8,12,16,20,55"; |
416 option--; |
|
388 /* COBOL, normal format */ 389 break; 390 case '2': 391 tab_list = "1,6,10,14,49"; 392 /* COBOL compact format */ 393 break; 394 case '3': 395 tab_list = "1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67"; 396 /* COBOL compact format extended */ 397 break; | 417 /* COBOL, normal format */ 418 break; 419 case '2': 420 tab_list = "1,6,10,14,49"; 421 /* COBOL compact format */ 422 break; 423 case '3': 424 tab_list = "1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67"; 425 /* COBOL compact format extended */ 426 break; |
398 default: 399 usage(); | |
400 } 401 break; 402 case 'd': /* ncurses extension */ 403 debug = TRUE; 404 break; 405 case 'f': 406 tab_list = "1,7,11,15,19,23"; 407 /* FORTRAN */ --- 14 unchanged lines hidden (view full) --- 422 /* UNIVAC 1100 Assembler */ 423 break; 424 case 'T': 425 ++n; 426 if (*++option != '\0') { 427 term_name = option; 428 } else { 429 term_name = argv[n++]; | 427 } 428 break; 429 case 'd': /* ncurses extension */ 430 debug = TRUE; 431 break; 432 case 'f': 433 tab_list = "1,7,11,15,19,23"; 434 /* FORTRAN */ --- 14 unchanged lines hidden (view full) --- 449 /* UNIVAC 1100 Assembler */ 450 break; 451 case 'T': 452 ++n; 453 if (*++option != '\0') { 454 term_name = option; 455 } else { 456 term_name = argv[n++]; |
457 option--; |
|
430 } 431 option += ((int) strlen(option)) - 1; 432 continue; | 458 } 459 option += ((int) strlen(option)) - 1; 460 continue; |
461 case 'V': 462 puts(curses_version()); 463 ExitProgram(EXIT_SUCCESS); |
|
433 default: 434 if (isdigit(UChar(*option))) { | 464 default: 465 if (isdigit(UChar(*option))) { |
435 tab_list = option; 436 ++n; | 466 char *copy = strdup(option); 467 *skip_list(copy) = '\0'; 468 tab_list = copy; 469 option = skip_list(option) - 1; |
437 } else { 438 usage(); 439 } | 470 } else { 471 usage(); 472 } |
440 option += ((int) strlen(option)) - 1; | |
441 break; 442 } 443 } 444 break; 445 case '+': 446 while ((ch = *++option) != '\0') { 447 switch (ch) { 448 case 'm': | 473 break; 474 } 475 } 476 break; 477 case '+': 478 while ((ch = *++option) != '\0') { 479 switch (ch) { 480 case 'm': |
449 mar_list = option; | 481 /* 482 * The "+mXXX" option is unimplemented because only the long-obsolete 483 * att510d implements smgl, which is needed to support 484 * this option. 485 */ |
450 break; 451 default: 452 /* special case of relative stops separated by spaces? */ 453 if (option == argv[n] + 1) { 454 tab_list = add_to_tab_list(&append, argv[n]); 455 } 456 break; 457 } --- 14 unchanged lines hidden (view full) --- 472 473 setupterm(term_name, STDOUT_FILENO, (int *) 0); 474 475 max_cols = (columns > 0) ? columns : 80; 476 477 if (!VALID_STRING(clear_all_tabs)) { 478 fprintf(stderr, 479 "%s: terminal type '%s' cannot reset tabs\n", | 486 break; 487 default: 488 /* special case of relative stops separated by spaces? */ 489 if (option == argv[n] + 1) { 490 tab_list = add_to_tab_list(&append, argv[n]); 491 } 492 break; 493 } --- 14 unchanged lines hidden (view full) --- 508 509 setupterm(term_name, STDOUT_FILENO, (int *) 0); 510 511 max_cols = (columns > 0) ? columns : 80; 512 513 if (!VALID_STRING(clear_all_tabs)) { 514 fprintf(stderr, 515 "%s: terminal type '%s' cannot reset tabs\n", |
480 argv[0], term_name); | 516 prg_name, term_name); |
481 } else if (!VALID_STRING(set_tab)) { 482 fprintf(stderr, 483 "%s: terminal type '%s' cannot set tabs\n", | 517 } else if (!VALID_STRING(set_tab)) { 518 fprintf(stderr, 519 "%s: terminal type '%s' cannot set tabs\n", |
484 argv[0], term_name); 485 } else if (legal_tab_list(argv[0], tab_list)) { | 520 prg_name, term_name); 521 } else if (legal_tab_list(tab_list)) { |
486 int *list = decode_tabs(tab_list); 487 488 if (!no_op) 489 tputs(clear_all_tabs, 1, putch); 490 491 if (list != 0) { 492 if (!no_op) 493 do_tabs(list); --- 17 unchanged lines hidden --- | 522 int *list = decode_tabs(tab_list); 523 524 if (!no_op) 525 tputs(clear_all_tabs, 1, putch); 526 527 if (list != 0) { 528 if (!no_op) 529 do_tabs(list); --- 17 unchanged lines hidden --- |