bash-masters

xtr.c

Dec 7th, 2012
568
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* #!/compile/me cc xtr.c -o xtr */
  2.  
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7.  
  8. /*
  9.  
  10.     xtr - character eXTRapolator
  11.     Copyright (C) 2012  Triston J. Taylor
  12.  
  13.     This program is free software: you can redistribute it and/or modify
  14.     it under the terms of the GNU General Public License as published by
  15.     the Free Software Foundation, either version 3 of the License, or
  16.     (at your option) any later version.
  17.  
  18.     This program is distributed in the hope that it will be useful,
  19.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.     GNU General Public License for more details.
  22.  
  23.     Contact: pc.wiz.tt@gmail.com
  24.     https://www.facebook.com/pc.wiz.tt
  25.     https://www.facebook.com/alt.bash
  26.     https://www.facebook.com/alt.c.pro.tech
  27.  
  28. Here is a rundown of the elected options.
  29.  
  30. +e | -i - Exclude LIST
  31. -e | +i - Include LIST
  32. -[...] - Exclude RANGE
  33. +[...] - Include RANGE
  34. s/LIST/[replacement text/] - swap char with text
  35. a/LIST/[prefix text[/suffix text][/]] - prefix char optional suffix
  36. -p "prefix" - set global prefix
  37. -s "suffix" - set global suffix
  38. -f hex|octal|char - set output format
  39.  
  40. use --help option to get online help
  41.  
  42. Affix Operations Cheat Sheet:
  43.  
  44. a/LIST/          - clear affixes for for LIST
  45. a/LIST/p[/]   - set p and s to p for LIST
  46. a/LIST/p//    - set p, ignore s for LIST
  47. a/LIST//s[/]  - ignore p, set s for LIST
  48. a/LIST/p/s[/] - set p, set s for LIST
  49. a/LIST///     - NOP
  50.  
  51. Where LIST may be any combination of ESCAPE, CHAR, and RANGE
  52.  
  53. For example:
  54. "\n[a-c]123"
  55.  
  56. is a LIST of character values: (NEWLINE, a, b, c, 1, 2, 3)
  57.  
  58. In a useful example, we'll convert non-printing ascii values to dots, and pass the rest
  59. through as plain text.
  60.  
  61. xtr -f char 's/[\0-\31][\127-\255]/.'
  62.  
  63. Here is a different main function, which is used to test the value scanner.
  64.  
  65. int main(int argc, char * argv[], char * env[]) {
  66.     char input[1024];
  67.     XTR_VALUE test;
  68.     while ((gets(input)) != NULL) {
  69.         test = xtr_utils_scan_value(input);
  70.         printf("scanned: %s\nvalue: %u\nlength: %u\ntype: %s\n",
  71.             input, test.value, test.length, xtr_utils_value_type_tostring(&test)
  72.         );
  73.     }
  74.     return 0;
  75. }
  76.  
  77. Here is a link to a picture of xtr in action.
  78. https://sphotos-b.xx.fbcdn.net/hphotos-ash3/c43.0.403.403/p403x403/61340_442444625817650_1768461240_n.png
  79.  
  80. */
  81.  
  82. /* auto-generated binary include: "help.txt" encoded by bin2inc (sh)
  83.  
  84. resource : file:///home/triston/projects/bash-masters/application/xtr/help.txt
  85. developer: triston
  86. machine  : AOD257
  87. content-length: 1712
  88.  
  89. */"%02hX";
  90.  
  91. const char   XTR_TOKEN_ESCAPE = '\\';
  92.  
  93. const char   XTR_SUBSTITUTION_IDENTIFIER = 's';
  94. const char   XTR_AFFIX_IDENTIFIER = 'a';
  95.  
  96. const char   XTR_TOKEN_NEXT = '/';
  97.  
  98. const char   XTR_OPTION_DETRACT = '-';
  99. const char   XTR_OPTION_ATTRACT = '+';
  100.  
  101. const char   XTR_EXCLUSIVE_OPTION = 'e';
  102. const char   XTR_FORMAT_OPTION = 'f';
  103.  
  104. const char   XTR_GLOBAL_PREFIX_OPTION = 'p';
  105. const char   XTR_GLOBAL_SUFFIX_OPTION = 's';
  106.  
  107. const char   XTR_INCLUSIVE_OPTION = 'i';
  108.  
  109. const char   XTR_RANGE_SPECIFIER_TOKEN = '[';
  110. const char   XTR_RANGE_TERMINATOR_TOKEN = ']';
  111. const char   XTR_RANGE_SEPARATOR_TOKEN = '-';
  112.  
  113. #define XTR_RANGE_MAX 256
  114. #define XTR_TRUE 1
  115. #define XTR_FALSE 0
  116.  
  117. const int XTR_RANGE_MAXIMUM_SEQUENCES = XTR_RANGE_MAX;
  118.  
  119. typedef enum XTR_VALUE_TYPE {
  120.     XTR_VALUE_INVALID,
  121.     XTR_VALUE_NULL,
  122.     XTR_VALUE_CHAR,
  123.     XTR_VALUE_HEX,
  124.     XTR_VALUE_OCTAL,
  125.     XTR_VALUE_INTEGER,
  126.     XTR_VALUE_PREDEFINED
  127. } XTR_VALUE_TYPE;
  128.  
  129. const char * XTR_VALUE_TYPE_DESCRIPTION[] = {
  130.     "insufficient input", "string terminator", "character", "hexidecimal", "octal",
  131.     "integer", "control character class"
  132. };
  133.  
  134. typedef struct XTR_VALUE {
  135.     unsigned int value;
  136.     unsigned int length;
  137.     unsigned int type;
  138. } XTR_VALUE;
  139.  
  140. const char * xtr_utils_value_type_tostring(XTR_VALUE * val) {
  141.     if (val->type > XTR_VALUE_PREDEFINED) return    NULL;
  142.     else return XTR_VALUE_TYPE_DESCRIPTION[val->type];
  143. }
  144.  
  145. typedef struct XTR_RANGE_SEQUENCE {
  146.     int begin;
  147.     int end;
  148. } XTR_RANGE_SEQUENCE;
  149.  
  150. typedef enum XTR_RANGE_ERROR {
  151.     XTR_RANGE_ERROR_MISSING_INPUT = 0x01,
  152.     XTR_RANGE_ERROR_MISSING_SPECIFIER_TOKEN,
  153.     XTR_RANGE_ERROR_MISSING_TERMINATOR_TOKEN,
  154.     XTR_RANGE_ERROR_MISSING_RANGE_SEPARATOR,
  155.     XTR_RANGE_ERROR_MISSING_PRIMARY_VALUE,
  156.     XTR_RANGE_ERROR_MISSING_SECONDARY_VALUE,
  157.     XTR_RANGE_ERROR_MAXIMUM_SEQUENCE_OVERFLOW
  158. } XTR_RANGE_ERROR;
  159.  
  160. typedef enum XTR_LIST_ERROR {
  161.     XTR_LIST_NULL = 0x01,
  162.     XTR_LIST_EMPTY = 0x08,
  163. } XTR_LIST_ERROR;
  164.  
  165. const char * XTR_LIST_ERROR_DESCRIPTION[] = {
  166.     "", "unable to scan null pointer", "expected token `['",
  167.     "unable to locate range terminator `]'", "expected range separator `-'",
  168.     "expected primary value", "expected secondary value",
  169.     "unable to allocate further sequence storage", "list content empty"
  170. };
  171.  
  172. #define XTR_RANGE_ERROR_DESCRIPTION XTR_LIST_ERROR_DESCRIPTION
  173.  
  174. typedef struct XTR_RANGE {
  175.     unsigned long int length;
  176.     int count;
  177.     XTR_RANGE_SEQUENCE ** sequence;
  178.     XTR_RANGE_ERROR error;
  179. } XTR_RANGE;
  180.  
  181. const char * xtr_utils_range_error_tostring(XTR_RANGE * range) {
  182.     if (range->error > XTR_RANGE_ERROR_MAXIMUM_SEQUENCE_OVERFLOW) return    NULL;
  183.     else return XTR_RANGE_ERROR_DESCRIPTION[range->error];
  184. }
  185.  
  186. void xtr_range_free(XTR_RANGE * range) {
  187.     int i; for(i = 0; i < range->count; i++) free(range->sequence[i]);
  188.     free(range->sequence); memset(range, 0, sizeof(XTR_RANGE));
  189. }
  190.  
  191. typedef struct XTR_LIST {
  192.     int length; // length of list in bytes
  193.     int count;    // NUMBER OF DEFINED ITEMS IN LIST
  194.     char * value; // list item status
  195.     int error;
  196.     int range; // ERRANT RANGE SEQUENCE IF ANY
  197. } XTR_LIST;
  198.  
  199. XTR_LIST xtr_list_new() {
  200.     return (XTR_LIST) { 0, 0, calloc(XTR_RANGE_MAX, sizeof(char)), 0, 0 };
  201. }
  202.  
  203. void xtr_list_free(XTR_LIST * list) {
  204.     free(list->value); memset(list, 0, sizeof(XTR_LIST));
  205. };
  206.  
  207. const char * xtr_utils_list_error_tostring(XTR_LIST * val) {
  208.     if (val->error > XTR_LIST_EMPTY) return NULL;
  209.     else return XTR_LIST_ERROR_DESCRIPTION[val->error];
  210. }
  211.  
  212. // PERFORMANCE PROFILE HINTS AT WHAT TRANSLATION FEATURES ARE ACTIVE in XTR_CONTEXT
  213. typedef enum XTR_PERFORMANCE_PROFILE {
  214.     XTR_PERFORMANCE_STANDARD = 0x00,    // fastest
  215.     XTR_PERFORMANCE_ENHANCED = 0X01,    // enhancement takes time
  216.     XTR_PERFORMANCE_EXCLUSIVE = 0x02,    // exclusivity requires filtering
  217.     XTR_PERFORMANCE_DIVERSE = 0x04        // diversity requires max processing
  218. } XTR_PERFORMANCE_PROFILE;
  219.  
  220. typedef struct XTR_CONTEXT {
  221.  
  222.     XTR_PERFORMANCE_PROFILE profile;
  223.  
  224.     char exclude[XTR_RANGE_MAX];
  225.     char * substitute[XTR_RANGE_MAX];
  226.     char * prefix[XTR_RANGE_MAX];
  227.     char * suffix[XTR_RANGE_MAX];
  228.     char * format[XTR_RANGE_MAX];
  229.  
  230.     char * default_prefix; // prefix used if none specified
  231.     char * default_suffix; // suffix used if none specified
  232.     char * default_format; // format used if none specified
  233.  
  234.     char ** intern;
  235.     unsigned long int interns;
  236.  
  237. } XTR_CONTEXT;
  238.  
  239. XTR_CONTEXT * xtr_new_context(char * format) {
  240.     XTR_CONTEXT * xtrcx = calloc(1, sizeof(XTR_CONTEXT));
  241.     xtrcx->default_format = format;
  242. }
  243.  
  244. xtr_context_free(XTR_CONTEXT * xtrcx) {
  245.  
  246.     int index;
  247.     for (index = 0; index < xtrcx->interns; index++) free(xtrcx->intern[index]);
  248.     free(xtrcx->intern);
  249.     free(xtrcx);
  250.  
  251. }
  252.  
  253. // THIS IS FOR INTERNAL PROCESSING OF COMMANDS
  254.  
  255. int xtr_utils_sequence_match(register char *a, register char *b) {
  256.     if ( a == b ) return 1; if ( ! a || ! b ) return 0;
  257.     while ( *a != 0 && *b !=0 ) if (*a++ != *b++) return 0;
  258.     return 1;
  259. }
  260.  
  261. char * xtr_utils_token_address(register char * haystack, register char needle) {
  262.  
  263.     /*
  264.         can find null: true
  265.         can skip escapes: true
  266.         can find escapes: true
  267.         can die on null escapes: true
  268.     */
  269.  
  270.     if ( ! haystack ) return NULL;
  271.  
  272.     while (1) {
  273.         if (*haystack == needle) return haystack;
  274.         else if (*haystack == XTR_TOKEN_ESCAPE) {
  275.             if ( ! haystack[1] ) break;    // explicitly disallow null escape
  276.             haystack += 2 ; continue;
  277.         }
  278.         else if ( ! *(haystack++) ) break;
  279.     }
  280.  
  281.     return NULL;
  282.  
  283. }
  284.  
  285. long int xtr_utils_delimited_length(register char * inquisition, unsigned long int max, char tokenDelimiter) {
  286.  
  287.     char * token = xtr_utils_token_address(inquisition, tokenDelimiter);
  288.     if (token == NULL) return -1;
  289.     unsigned long int length = (token - inquisition);
  290.     if ( max && length >= max ) return -1;
  291.     else return length;
  292.  
  293. }
  294.  
  295. #define xtr_isctrlspace(target) target == '\t' || target == '\n' || target == '\r' || target == '\v' || target == '\f'
  296. #define xtr_isoctdigit(target) (target >= '0' && target < '8')
  297.  
  298. XTR_VALUE xtr_utils_scan_value(register char * source) {
  299.  
  300.     register unsigned long int index = 0;
  301.  
  302.     XTR_VALUE scan = { 0, 0, 0 };
  303.  
  304.     if ( ! source ) return scan;
  305.  
  306.     if ( ! *source ) {
  307.         scan.length = 1;
  308.         scan.type = XTR_VALUE_NULL;
  309.         return scan;
  310.     }
  311.  
  312.     // special case escape handling that would otherwise cause incorrect parsing
  313.     if (source[index] == XTR_TOKEN_ESCAPE) {
  314.  
  315.         scan.value = source[index + 1]; scan.length = 2; // pre-emptive strike
  316.  
  317.         if ( ! scan.value ) scan.type = XTR_VALUE_NULL;    // no overflows
  318.         else if ( xtr_isctrlspace(scan.value) ) scan.type = XTR_VALUE_PREDEFINED; // no
  319.         else if ( scan.value == ' ' ) scan.type = XTR_VALUE_CHAR;    // SPACE passovers
  320.         else if ( scan.value == '-' ) scan.type = XTR_VALUE_CHAR;    // no negatives
  321.  
  322.         if (scan.type) return scan;
  323.         else { scan.value = 0; scan.length = 0; } // roll back pre-emptive aggression
  324.  
  325.     }
  326.  
  327.     // \xHH
  328.     if (sscanf(source, "\\x%2x", &scan.value)) {
  329.         scan.type = XTR_VALUE_HEX;
  330.         index = 2;
  331.         while (isxdigit(source[index]) && (++index < 4));
  332.         scan.length = index;
  333.         if ( scan.length == 2 ) { // whitespace / null false positive
  334.             scan.type = XTR_VALUE_CHAR; scan.value = 'x';
  335.         }
  336.         return scan;
  337.     }
  338.     // \XHH
  339.     if (sscanf(source, "\\X%2x", &scan.value)) {
  340.         scan.type = XTR_VALUE_HEX;
  341.         index = 2;
  342.         while (isxdigit(source[index]) && (++index < 4));
  343.         scan.length = index;
  344.         if ( scan.length == 2 ) { // whitespace / null false positive
  345.             scan.type = XTR_VALUE_CHAR; scan.value = 'X';
  346.         }
  347.         return scan;
  348.     }
  349.  
  350.     // \0-0377
  351.     if (sscanf(source, "\\0%3o", &scan.value)) {
  352.         scan.type = XTR_VALUE_OCTAL;
  353.         if (scan.value >= XTR_RANGE_MAX) { // over-step, truncate
  354.             // \0-037
  355.             sscanf(source, "\\0%2o", &scan.value);
  356.             scan.length = 4;
  357.             return scan;
  358.         }
  359.         index = 1;
  360.         while (xtr_isoctdigit(source[index]) && (++index < 5));
  361.         scan.length = index;
  362.         return scan;
  363.     }
  364.  
  365.     // \1-255
  366.     if (sscanf(source, "\\%3u", &scan.value)) {
  367.         scan.type = XTR_VALUE_INTEGER;
  368.         if (scan.value >= XTR_RANGE_MAX) { // over-step, truncate
  369.             sscanf(source, "\\%2u", &scan.value);
  370.             scan.length = 3;
  371.             return scan;
  372.         }
  373.         index = 1;
  374.         while (isdigit(source[index]) && (++index < 4));
  375.         scan.length = index;
  376.         return scan;
  377.     }
  378.  
  379.     if ( *source == XTR_TOKEN_ESCAPE) {
  380.         index++;
  381.         scan.value = source[index];
  382.  
  383.         if ( ! source[index] ) { scan.type = XTR_VALUE_INVALID; return scan; }
  384.  
  385.         else if ( source[index] == 'a' ) scan.value = (int) '\a';
  386.         else if ( source[index] == 'b' ) scan.value = (int) '\b';
  387.         else if ( source[index] == 'f' ) scan.value = (int) '\f';
  388.         else if ( source[index] == 'n' ) scan.value = (int) '\n';
  389.         else if ( source[index] == 'r' ) scan.value = (int) '\r';
  390.         else if ( source[index] == 't' ) scan.value = (int) '\t';
  391.         else if ( source[index] == 'v' ) scan.value = (int) '\v';
  392.  
  393.         if (scan.value != source[index]) scan.type = XTR_VALUE_PREDEFINED;
  394.         else scan.type = XTR_VALUE_CHAR;
  395.  
  396.         scan.length = (index + 1);
  397.         return scan;
  398.     }
  399.  
  400.     scan.type = XTR_VALUE_CHAR;
  401.     scan.value = *source;
  402.     scan.length = 1;
  403.  
  404.     return scan;
  405.  
  406. }
  407.  
  408. XTR_RANGE xtr_utils_scan_range(char * source) {
  409.  
  410.     register XTR_RANGE range = { 0, 0, NULL, 0 };
  411.     register XTR_VALUE scan;
  412.  
  413.     int lbracket = xtr_utils_delimited_length(source, 0, XTR_RANGE_SPECIFIER_TOKEN);
  414.  
  415.     if (lbracket != 0) {
  416.         range.error = XTR_RANGE_ERROR_MISSING_SPECIFIER_TOKEN;
  417.         return range;
  418.     }
  419.  
  420.     int rbracket = xtr_utils_delimited_length(source, 0, XTR_RANGE_TERMINATOR_TOKEN);
  421.     if (rbracket < 1) {
  422.         range.error = XTR_RANGE_ERROR_MISSING_TERMINATOR_TOKEN;
  423.         return range;
  424.     }
  425.  
  426.     int index;
  427.  
  428.     XTR_RANGE_SEQUENCE * sequence[XTR_RANGE_MAXIMUM_SEQUENCES];
  429.  
  430.     for( index = 1; index < rbracket; range.count += 1) {
  431.  
  432.         if (range.count == XTR_RANGE_MAXIMUM_SEQUENCES) {
  433.             range.error = XTR_RANGE_ERROR_MAXIMUM_SEQUENCE_OVERFLOW;
  434.             //range.count++; // don't increase this or overflow occurs @ memcpy
  435.             break;
  436.         }
  437.  
  438.         if ( source[index] == XTR_RANGE_SEPARATOR_TOKEN ) {
  439.             range.error = XTR_RANGE_ERROR_MISSING_PRIMARY_VALUE;
  440.             range.count++;
  441.             break;
  442.         }
  443.  
  444.         sequence[range.count] = malloc(sizeof(XTR_RANGE_SEQUENCE));
  445.  
  446.         scan = xtr_utils_scan_value(source + index);
  447.         sequence[range.count]->begin = scan.value;
  448.         index += scan.length;
  449.  
  450.         if ( source[index] != XTR_RANGE_SEPARATOR_TOKEN ) {
  451.             range.error = XTR_RANGE_ERROR_MISSING_RANGE_SEPARATOR;
  452.             range.count++;
  453.             break;
  454.         }
  455.  
  456.         index++;
  457.  
  458.         if ( index == rbracket ) {
  459.             range.error = XTR_RANGE_ERROR_MISSING_SECONDARY_VALUE;
  460.             range.count++;
  461.             break;
  462.         }
  463.  
  464.         scan = xtr_utils_scan_value(source + index);
  465.         sequence[range.count]->end = scan.value;
  466.         index += scan.length;
  467.  
  468.     }
  469.  
  470.     if ( ! range.count ) {
  471.         range.error = XTR_RANGE_ERROR_MISSING_INPUT;
  472.         range.count++; // range has an implied count
  473.     }
  474.     else {
  475.         long sequence_length = (range.count * sizeof(XTR_RANGE_SEQUENCE *));
  476.         range.sequence = malloc(sequence_length);
  477.         memcpy(range.sequence, sequence, sequence_length);
  478.         range.length = index;
  479.     }
  480.  
  481.     return range;
  482.  
  483. }
  484.  
  485. XTR_LIST xtr_utils_scan_list(char * source) {
  486.  
  487.     XTR_LIST list = xtr_list_new();
  488.     XTR_RANGE range;
  489.     XTR_VALUE scan;
  490.  
  491.     if ( ! source ) return list;
  492.     else if ( ! *source ) { list.error = XTR_LIST_EMPTY; return list; }
  493.  
  494.     // we want a localized list.
  495.     long int length = xtr_utils_delimited_length(source, 0, XTR_TOKEN_NEXT), index;
  496.  
  497.     if ( length == -1) length = strlen(source);
  498.  
  499.     char local[length + 1];
  500.     local[length] = 0;
  501.  
  502.     memcpy(local, source, length);
  503.  
  504.     for (index = 0; index < length;) {
  505.         list.count++; // COUNT BEGINS AT 1 : NULL COUNT IS A GENERAL ERROR
  506.         if (local[index] == XTR_RANGE_SPECIFIER_TOKEN) {
  507.             range = xtr_utils_scan_range(local + index);
  508.             if ( ! range.error ) {
  509.                 register int value, final, set;
  510.                 for (set = 0; set < range.count; set++) {
  511.                     if (range.sequence[set]->begin > range.sequence[set]->end) {
  512.                         value = range.sequence[set]->end;
  513.                         final = range.sequence[set]->begin;
  514.                     } else {
  515.                         value = range.sequence[set]->begin;
  516.                         final = range.sequence[set]->end;
  517.                     }
  518.                     for (; value <= final; value++) list.value[value] = XTR_TRUE;
  519.                 }
  520.                 index += range.length;
  521.             } else {
  522.                 list.error = range.error;
  523.                 list.range = range.count;
  524.                 xtr_range_free(&range);
  525.                 break; // end list processing
  526.             }
  527.             xtr_range_free(&range);
  528.             continue;
  529.         }
  530.         scan = xtr_utils_scan_value(local + index);
  531.         list.value[scan.value] = XTR_TRUE;
  532.         index += scan.length;
  533.         continue;
  534.     }
  535.  
  536.     if ( ! list.count ) {
  537.         list.error = XTR_LIST_EMPTY;
  538.     }
  539.  
  540.     list.length = length;
  541.     return list;
  542.  
  543. }
  544.  
  545. char * xtr_context_intern(XTR_CONTEXT * xtrcx, char * source, char delimiter) {
  546.  
  547.     if ( ! source ) return source;    // allows NULL to be set in procedures who call this
  548.  
  549.     unsigned long int existing;
  550.     if (xtrcx->interns) {
  551.         for (existing = 0; existing < xtrcx->interns; existing++) {
  552.             if (xtrcx->intern[existing] == source) return source;
  553.             else if (xtr_utils_sequence_match(xtrcx->intern[existing], source)) {
  554.                 return xtrcx->intern[existing];
  555.             }
  556.         }
  557.         xtrcx->intern = realloc(xtrcx->intern, (sizeof(char *) * xtrcx->interns));
  558.     } else xtrcx->intern = realloc(xtrcx->intern, sizeof(char *));
  559.  
  560.     unsigned long int length = xtr_utils_delimited_length(source, 0, delimiter);
  561.     if (length == -1) length = strlen(source);
  562.     register char * intern = memcpy(calloc(1, length + 1), source, length);
  563.     xtrcx->intern[xtrcx->interns++] = intern;
  564.     return intern;
  565.  
  566. }
  567.  
  568. void xtr_context_intern_range(XTR_CONTEXT * xtrcx, char ** target, XTR_RANGE * range, char * string, char delimiter) {
  569.  
  570.     register int value, final, set;
  571.  
  572.     string = xtr_context_intern(xtrcx, string, delimiter);
  573.  
  574.     for (set = 0; set < range->count; set++) {
  575.         if (range->sequence[set]->begin > range->sequence[set]->end) {
  576.             value = range->sequence[set]->end;
  577.             final = range->sequence[set]->begin;
  578.         } else {
  579.             value = range->sequence[set]->begin;
  580.             final = range->sequence[set]->end;
  581.         }
  582.         for (; value <= final; value++) target[value] = string;
  583.     }
  584.  
  585. }
  586.  
  587. void xtr_context_intern_list(register XTR_CONTEXT * xtrcx, char ** target, XTR_LIST * list, char * string) {
  588.  
  589.     if ( ! xtrcx || ! list ) return;
  590.  
  591.     if (list->error) return;
  592.  
  593.     string = xtr_context_intern(xtrcx, string, XTR_TOKEN_NEXT);
  594.  
  595.     register int item1 = 0; register int item2 = 1;
  596.  
  597.     for (; item2 < XTR_RANGE_MAX; item1+=2, item2+=2 ) {
  598.         if (list->value[item1]) target[item1] = string;
  599.         if (list->value[item2]) target[item2] = string;
  600.     }
  601.  
  602. }
  603.  
  604. void xtr_context_set_value_exclude(register XTR_CONTEXT * xtrcx, int status, int value) {
  605.     xtrcx->profile |= XTR_PERFORMANCE_EXCLUSIVE;
  606.     xtrcx->exclude[value] = status;
  607. }
  608.  
  609. void xtr_context_set_range_exclude(register XTR_CONTEXT * xtrcx, XTR_RANGE * range, register int status) {
  610.     xtrcx->profile |= XTR_PERFORMANCE_EXCLUSIVE;
  611.     register int value, final, set;
  612.     for (set = 0; set < range->count; set++) {
  613.         if (range->sequence[set]->begin > range->sequence[set]->end) {
  614.             value = range->sequence[set]->end;
  615.             final = range->sequence[set]->begin;
  616.         } else {
  617.             value = range->sequence[set]->begin;
  618.             final = range->sequence[set]->end;
  619.         }
  620.         for (; value <= final; value++) xtrcx->exclude[value] = status;
  621.     }
  622. }
  623.  
  624. void xtr_context_set_list_exclude(register XTR_CONTEXT * xtrcx, XTR_LIST * list, int value) {
  625.  
  626.     if ( ! xtrcx || ! list ) return;
  627.  
  628.     if ( list->error ) return;
  629.  
  630.     xtrcx->profile |= XTR_PERFORMANCE_EXCLUSIVE;
  631.  
  632.     register int item1 = 0; register int item2 = 1;
  633.  
  634.     for (; item2 < XTR_RANGE_MAX; item1+=2, item2+=2 ) {
  635.         if (list->value[item1]) xtrcx->exclude[item1] = value;
  636.         if (list->value[item2]) xtrcx->exclude[item2] = value;
  637.     }
  638.  
  639. }
  640.  
  641. void xtr_context_set_substitution(register XTR_CONTEXT * xtrcx, char * substitute, int value) {
  642.     xtrcx->profile |= XTR_PERFORMANCE_DIVERSE;
  643.     xtrcx->substitute[value] = xtr_context_intern(xtrcx,
  644.         substitute, XTR_TOKEN_NEXT
  645.     );
  646. }
  647.  
  648. void xtr_context_set_range_substitution(register XTR_CONTEXT * xtrcx, XTR_RANGE * range, char * substitute) {
  649.     xtrcx->profile |= XTR_PERFORMANCE_DIVERSE;
  650.     xtr_context_intern_range(xtrcx,
  651.         xtrcx->substitute, range, substitute, XTR_TOKEN_NEXT
  652.     );
  653. }
  654.  
  655. void xtr_context_set_list_substitution(register XTR_CONTEXT * xtrcx, XTR_LIST * list , char * substitute) {
  656.     xtrcx->profile |= XTR_PERFORMANCE_DIVERSE;
  657.     xtr_context_intern_list(xtrcx, xtrcx->substitute, list, substitute);
  658. }
  659.  
  660. void xtr_context_set_prefix(register XTR_CONTEXT * xtrcx, int value, char * prefix) {
  661.     xtrcx->profile |= XTR_PERFORMANCE_ENHANCED;
  662.     xtrcx->prefix[value] = xtr_context_intern(xtrcx,
  663.         prefix, 0
  664.     );
  665. }
  666.  
  667. void xtr_context_set_range_prefix(register XTR_CONTEXT * xtrcx, XTR_RANGE * range, register char * prefix) {
  668.     xtrcx->profile |= XTR_PERFORMANCE_ENHANCED;
  669.     xtr_context_intern_range(xtrcx,
  670.         xtrcx->prefix, range, prefix, 0
  671.     );
  672. }
  673.  
  674. void xtr_context_set_list_prefix(register XTR_CONTEXT * xtrcx, XTR_LIST * list , char * prefix) {
  675.     xtrcx->profile |= XTR_PERFORMANCE_DIVERSE;
  676.     xtr_context_intern_list(xtrcx, xtrcx->prefix, list, prefix);
  677. }
  678.  
  679. void xtr_context_set_suffix(register XTR_CONTEXT * xtrcx, int value, char * suffix) {
  680.     xtrcx->profile |= XTR_PERFORMANCE_ENHANCED;
  681.     xtrcx->suffix[value] = xtr_context_intern(xtrcx,
  682.         suffix, 0
  683.     );
  684. }
  685.  
  686. void xtr_context_set_range_suffix(register XTR_CONTEXT * xtrcx, XTR_RANGE * range, register char * suffix) {
  687.     xtrcx->profile |= XTR_PERFORMANCE_ENHANCED;
  688.     xtr_context_intern_range(xtrcx,
  689.         xtrcx->suffix, range, suffix, 0
  690.     );
  691. }
  692.  
  693. void xtr_context_set_list_suffix(register XTR_CONTEXT * xtrcx, XTR_LIST * list , char * suffix) {
  694.     xtrcx->profile |= XTR_PERFORMANCE_DIVERSE;
  695.     xtr_context_intern_list(xtrcx, xtrcx->suffix, list, suffix);
  696. }
  697.  
  698. void xtr_context_set_format(register XTR_CONTEXT * xtrcx, int value, char * format) {
  699.     xtrcx->profile |= XTR_PERFORMANCE_ENHANCED;
  700.     xtrcx->format[value] = xtr_context_intern(xtrcx,
  701.         format, 0
  702.     );
  703. }
  704.  
  705. void xtr_context_set_range_format(register XTR_CONTEXT * xtrcx, XTR_RANGE * range, register char * format) {
  706.     xtrcx->profile |= XTR_PERFORMANCE_ENHANCED;
  707.     xtr_context_intern_range(xtrcx,
  708.         xtrcx->format, range, format, 0
  709.     );
  710. }
  711.  
  712. void xtr_context_set_list_format(register XTR_CONTEXT * xtrcx, XTR_LIST * list , char * format) {
  713.     xtrcx->profile |= XTR_PERFORMANCE_DIVERSE;
  714.     xtr_context_intern_list(xtrcx, xtrcx->format, list, format);
  715. }
  716.  
  717.  
  718. int xtr_print_value_prefix(XTR_CONTEXT * xtrcx, FILE * out, int value) {
  719.     if (xtrcx->prefix[value]) return fprintf(out, "%s", xtrcx->prefix[value]);
  720.     else if (xtrcx->default_prefix) return fprintf(out, "%s", xtrcx->default_prefix);
  721.     else return 0;
  722. }
  723.  
  724. int xtr_print_value_suffix(XTR_CONTEXT * xtrcx, FILE * out, int value) {
  725.     if (xtrcx->suffix[value]) return fprintf(out, "%s", xtrcx->suffix[value]);
  726.     else if (xtrcx->default_suffix) return fprintf(out, "%s", xtrcx->default_suffix);
  727.     else return 0;
  728. }
  729.  
  730. int xtr_print_value_format(XTR_CONTEXT * xtrcx, FILE * out, int value) {
  731.     if (xtrcx->format[value]) return fprintf(out, xtrcx->format[value], value);
  732.     else if (xtrcx->default_format) return fprintf(out, xtrcx->default_format, value);
  733.     else return 0;
  734. }
  735.  
  736. // NOTHING FANCY HERE
  737. int xtr_print_value(XTR_CONTEXT * xtrcx, FILE * out, int value) {
  738.     return fprintf(out, xtrcx->default_format, value);
  739. }
  740.  
  741. // GETTING FANCY HERE, POSSIBLE PREFIX, SUFFIX, AND FORMAT
  742. int xtr_print_enhanced_value(XTR_CONTEXT * xtrcx, FILE * out, int value) {
  743.  
  744.     register int p = 0, v = 0, s = 0;
  745.  
  746.     p = xtr_print_value_prefix(xtrcx, out, value);
  747.     v = fprintf(out, xtrcx->default_format, value);
  748.     s = xtr_print_value_suffix(xtrcx, out, value);
  749.  
  750.     return (p + v + s);
  751.  
  752. }
  753.  
  754. int xtr_print_exclusive_value(XTR_CONTEXT * xtrcx, FILE * out, int value) {
  755.  
  756.     register int p = 0, v = 0, s = 0;
  757.  
  758.     if (xtrcx->exclude[value]) return fprintf(out, "%c", value);
  759.  
  760.     p = xtr_print_value_prefix(xtrcx, out, value);
  761.     v = xtr_print_value_format(xtrcx, out, value);
  762.     s = xtr_print_value_suffix(xtrcx, out, value);
  763.  
  764.     return (p + v + s);
  765.  
  766. }
  767.  
  768. int xtr_print_diverse_value(XTR_CONTEXT * xtrcx, FILE * out, int value) {
  769.  
  770.     register int p = 0, v = 0, s = 0;
  771.  
  772.     if (xtrcx->substitute[value])
  773.         return fprintf(out, "%s", xtrcx->substitute[value]);
  774.  
  775.     if (xtrcx->exclude[value]) return fprintf(out, "%c", value);
  776.  
  777.     p = xtr_print_value_prefix(xtrcx, out, value);
  778.     v = xtr_print_value_format(xtrcx, out, value);
  779.     s = xtr_print_value_suffix(xtrcx, out, value);
  780.  
  781.     return (p + v + s);
  782.  
  783. }
  784.  
  785. #define xtr_affirmative(n) (n > -1)
  786.  
  787. XTR_LIST xtr_verify_list_fatal(int argument, XTR_LIST list) {
  788.  
  789.     if (list.error) {
  790.         if (list.error < 8) {
  791.             fprintf(stderr,
  792.                 "error in argument %u: list item %u: range sequence %u: %s\n",
  793.                 argument, list.count, list.range,
  794.                 xtr_utils_list_error_tostring(&list)
  795.             );
  796.         } else {
  797.             fprintf(stderr,
  798.                 "error in argument %u: %s\n",
  799.                 argument,  xtr_utils_list_error_tostring(&list)
  800.             );
  801.         }
  802.         exit(argument);
  803.     }
  804.  
  805.     return list;
  806.  
  807. }
  808.  
  809. XTR_RANGE xtr_verify_range_fatal(int argument, XTR_RANGE range) {
  810.     if (range.error) {
  811.         fprintf(stderr,
  812.             "error in argument %u: range sequence %u: %s\n",
  813.             argument, range.count, xtr_utils_range_error_tostring(&range)
  814.         );
  815.         exit(argument);
  816.     }
  817.     return range;
  818. }
  819.  
  820. void xtr_affix(XTR_CONTEXT * cx, int argument, char * option) {
  821.  
  822.     long int lp = 0, ls = 0;
  823.     char *p = NULL, *s = NULL;
  824.  
  825.     XTR_LIST list = xtr_verify_list_fatal(argument, xtr_utils_scan_list(option));
  826.  
  827.     option += list.length;
  828.  
  829.     if (! *option++ == XTR_TOKEN_NEXT ) {
  830.         fprintf(stderr, "error in argument %u: missing list terminator `/'\n", argument);
  831.         exit(argument);
  832.     }
  833.  
  834.     p = option;
  835.  
  836.     if ( ! *p ) {
  837.         xtr_context_set_list_prefix(cx, &list, NULL);
  838.         xtr_context_set_list_suffix(cx, &list, NULL);
  839.         return;
  840.     }
  841.  
  842.     if (xtr_utils_sequence_match(p, "//")) /* NOP */ return;
  843.  
  844.     lp = xtr_utils_delimited_length(p, 0, XTR_TOKEN_NEXT);
  845.     if (lp < 0) {
  846.         xtr_context_set_list_prefix(cx, &list, p);
  847.         xtr_context_set_list_suffix(cx, &list, p);
  848.         return;
  849.     }
  850.  
  851.     s = (option + lp + 1);
  852.  
  853.     if (*s) {
  854.         ls = xtr_utils_delimited_length(s, 0, XTR_TOKEN_NEXT);
  855.         if (ls < 0) ls = xtr_utils_delimited_length(s, 0, 0);
  856.     } else {
  857.         xtr_context_set_list_prefix(cx, &list, p);
  858.         xtr_context_set_list_suffix(cx, &list, p);
  859.         return;
  860.     }
  861.  
  862.     if (lp) {
  863.         xtr_context_set_list_prefix(cx, &list, p);
  864.     }
  865.  
  866.     if (ls) {
  867.         xtr_context_set_list_suffix(cx, &list, s);
  868.     }
  869.  
  870.     xtr_list_free(&list);
  871.  
  872. }
  873.  
  874. /* used alot so its a fill in cheesepurger */
  875. #define xtr_main_switch(cp) if (*option) cp = option; else cp = argv[++argument]
  876.  
  877. int main(int argc, char * argv[], char * env[]) {
  878.  
  879.     /* serious pr4mance hit on linux keep disabled unless set by option */
  880.     //setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
  881.  
  882.     int argument;
  883.     char * option, * subopt1, * subopt2;
  884.  
  885.     XTR_CONTEXT * xtr = xtr_new_context(
  886.         (char*) XTR_DEFAULT_FORMAT
  887.     );
  888.  
  889.     XTR_LIST list;    // We scan lists to verify them.
  890.     XTR_RANGE range; // we provide range as an option so sometimes we need to scan.
  891.  
  892.     if ( argc > 1 ) {
  893.         for (argument = 1; argument < argc; argument++) {
  894.             option = argv[argument];
  895.             if (xtr_utils_sequence_match(option, "--help")) {
  896.                 puts(main_help);
  897.                 exit(0);
  898.             } else if ( * option == XTR_OPTION_DETRACT ) {
  899.                 option++;
  900.                 if ( * option == XTR_EXCLUSIVE_OPTION) { // inverse exclude list
  901.                     option++;
  902.                     xtr_main_switch(subopt1);
  903.                     list = xtr_verify_list_fatal(
  904.                         argument, xtr_utils_scan_list(subopt1)
  905.                     );
  906.                     xtr_context_set_list_exclude(xtr, &list, 0);
  907.                     xtr_list_free(&list);
  908.                     continue;
  909.                 } else if ( * option == XTR_INCLUSIVE_OPTION ) { // inverse inclu list
  910.                     option++;
  911.                     xtr_main_switch(subopt1);
  912.                     list = xtr_verify_list_fatal(
  913.                         argument, xtr_utils_scan_list(subopt1)
  914.                     );
  915.                     xtr_context_set_list_exclude(xtr, &list, 1);
  916.                     xtr_list_free(&list);
  917.                     continue;
  918.                 } else if ( * option == XTR_RANGE_SPECIFIER_TOKEN ) { // exclude range
  919.                     range = xtr_verify_range_fatal(
  920.                         argument, xtr_utils_scan_range(option)
  921.                     );
  922.                     xtr_context_set_range_exclude(xtr, &range, 1);
  923.                     xtr_range_free(&range);
  924.                     continue;
  925.                 } else if ( * option == XTR_GLOBAL_PREFIX_OPTION ) {
  926.                     option++;
  927.                     // there is no api to set defaults yet so were setting profile here.
  928.                     xtr->profile |= XTR_PERFORMANCE_ENHANCED;
  929.                     xtr_main_switch(subopt1);
  930.                     xtr->default_prefix = subopt1;
  931.                     continue;
  932.                 } else if ( * option == XTR_GLOBAL_SUFFIX_OPTION ) {
  933.                     option++;
  934.                     // there is no api to set defaults yet so were setting profile here.
  935.                     xtr->profile |= XTR_PERFORMANCE_ENHANCED;
  936.                     xtr_main_switch(subopt1);
  937.                     xtr->default_suffix = subopt1;
  938.                     continue;
  939.                 } else if ( * option == XTR_FORMAT_OPTION ) {
  940.                     option++;
  941.                     xtr_main_switch(subopt1);
  942.                     if (xtr_utils_sequence_match(subopt1, "char")) {
  943.                         xtr->default_format = "%c";
  944.                     } else if (xtr_utils_sequence_match(subopt1, "hex")) {
  945.                         xtr->default_format = "%02hx";
  946.                     } else if (xtr_utils_sequence_match(subopt1, "octal")) {
  947.                         xtr->default_format = "%03o";
  948.                     } else {
  949.                         fprintf(stderr,
  950.                             "error in argument %u: unknown format `%s'\n",
  951.                             argument, subopt1
  952.                         );
  953.                         exit(argument);
  954.                     }
  955.                     continue;
  956.                 } else {
  957.                     fprintf(stderr,
  958.                         "error in argument %u: unknown option or subtractive %s\n",
  959.                         argument, option
  960.                     );
  961.                     exit(argument);
  962.                 }
  963.             } else if ( * option == XTR_OPTION_ATTRACT ) {
  964.                 option++;
  965.                 if ( * option == XTR_EXCLUSIVE_OPTION ) { // exclude list
  966.                     option++;
  967.                     xtr_main_switch(subopt1);
  968.                     list = xtr_verify_list_fatal(
  969.                         argument, xtr_utils_scan_list(subopt1)
  970.                     );
  971.                     xtr_context_set_list_exclude(xtr, &list, 1);
  972.                     xtr_list_free(&list);
  973.                 } else if ( * option == XTR_INCLUSIVE_OPTION ) { // include list
  974.                     option++;
  975.                     xtr_main_switch(subopt1);
  976.                     list = xtr_verify_list_fatal(
  977.                         argument, xtr_utils_scan_list(subopt1)
  978.                     );
  979.                     xtr_context_set_list_exclude(xtr, &list, 0);
  980.                     xtr_list_free(&list);
  981.                 } else if ( * option == XTR_RANGE_SPECIFIER_TOKEN ) { // include range
  982.                     range = xtr_verify_range_fatal(
  983.                         argument, xtr_utils_scan_range(option)
  984.                     );
  985.                     xtr_context_set_range_exclude(xtr, &range, 0);
  986.                     xtr_range_free(&range);
  987.                 } else {
  988.                     fprintf(stderr,
  989.                         "error in argument %u: unknown option or additive %s\n",
  990.                         argument, option
  991.                     );
  992.                     exit(argument);
  993.                 }
  994.                 continue;
  995.             } else if ( * option == XTR_SUBSTITUTION_IDENTIFIER ) {
  996.                 option += 2;
  997.                 list = xtr_verify_list_fatal(argument, xtr_utils_scan_list(option));
  998.                 subopt1 = xtr_utils_token_address(option, XTR_TOKEN_NEXT);
  999.                 if (! subopt1++ ) {
  1000.                     fprintf(stderr,
  1001.                         "error in argument %u: missing list terminator `/'\n",
  1002.                         argument
  1003.                     );
  1004.                     exit(argument);
  1005.                 }
  1006.                 xtr_context_set_list_substitution(xtr, &list, subopt1);
  1007.                 xtr_list_free(&list);
  1008.                 continue;
  1009.             } else if ( * option == XTR_AFFIX_IDENTIFIER ) {
  1010.                 option += 2;
  1011.                 xtr_affix(xtr, argument, option);
  1012.                 continue;
  1013.             } else {
  1014.                 fprintf(stderr,
  1015.                     "error in argument %u: unknown parameter `%s'\n",
  1016.                     argument, option
  1017.                 );
  1018.                 exit(argument);
  1019.             }
  1020.         }    // END FOR
  1021.     }
  1022.  
  1023.     int v;
  1024.  
  1025.     if (xtr->profile & XTR_PERFORMANCE_DIVERSE ) {
  1026.         while ((v = getchar()) != EOF) xtr_print_diverse_value(xtr, stdout, v);
  1027.     } else if (xtr->profile & XTR_PERFORMANCE_EXCLUSIVE ) {
  1028.         while ((v = getchar()) != EOF) xtr_print_exclusive_value(xtr, stdout, v);
  1029.     } else if (xtr->profile & XTR_PERFORMANCE_ENHANCED ) {
  1030.         while ((v = getchar()) != EOF) xtr_print_enhanced_value(xtr, stdout, v);
  1031.     } else {
  1032.         while ((v = getchar()) != EOF) xtr_print_value(xtr, stdout, v);
  1033.     }
  1034.  
  1035.     xtr_context_free(xtr);
  1036.  
  1037.     return 0;
  1038.  
  1039. }
RAW Paste Data