The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/libsa/vers_rsrc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #ifndef KERNEL
    2 #include <libc.h>
    3 #include "vers_rsrc.h"
    4 #else
    5 #include <sys/systm.h>
    6 #include <libsa/vers_rsrc.h>
    7 #endif /* not KERNEL */
    8 
    9 #ifndef KERNEL
   10 #define PRIV_EXT
   11 #else
   12 #define PRIV_EXT  __private_extern__
   13 #endif /* not KERNEL */
   14 
   15 #define VERS_MAJOR_DIGITS        (4)
   16 #define VERS_MINOR_DIGITS        (2)
   17 #define VERS_REVISION_DIGITS     (2)
   18 #define VERS_STAGE_DIGITS        (1)
   19 #define VERS_STAGE_LEVEL_DIGITS  (3)
   20 
   21 #define VERS_MAJOR_MULT    (100000000)
   22 #define VERS_MINOR_MULT      (1000000)
   23 #define VERS_REVISION_MULT     (10000)
   24 #define VERS_STAGE_MULT         (1000)
   25 
   26 typedef enum {
   27     VERS_invalid     = 0,
   28     VERS_development = 1,
   29     VERS_alpha       = 3,
   30     VERS_beta        = 5,
   31     VERS_candidate   = 7,
   32     VERS_release     = 9,
   33 } VERS_stage;
   34 
   35 
   36 static int __vers_isdigit(char c) {
   37     return (c == '' ||
   38         c == '1' || c == '2' || c == '3' ||
   39         c == '4' || c == '5' || c == '6' ||
   40         c == '7' || c == '8' || c == '9');
   41 }
   42 
   43 static int __vers_isspace(char c) {
   44     return (c == ' ' ||
   45         c == '\t' ||
   46         c == '\r' ||
   47         c == '\n');
   48 }
   49 
   50 static int __vers_digit_for_char(char c) {
   51     switch (c) {
   52       case '': return 0; break;
   53       case '1': return 1; break;
   54       case '2': return 2; break;
   55       case '3': return 3; break;
   56       case '4': return 4; break;
   57       case '5': return 5; break;
   58       case '6': return 6; break;
   59       case '7': return 7; break;
   60       case '8': return 8; break;
   61       case '9': return 9; break;
   62       default:  return -1; break;
   63     }
   64 
   65     return -1;
   66 }
   67 
   68 static int __VERS_isreleasestate(char c) {
   69     return (c == 'd' || c == 'a' || c == 'b' || c == 'f');
   70 }
   71 
   72 
   73 static VERS_stage __VERS_stage_for_string(char ** string_p) {
   74     char * string;
   75 
   76     if (!string_p || !*string_p) {
   77         return VERS_invalid;
   78     }
   79 
   80     string = *string_p;
   81 
   82     if (__vers_isspace(string[0]) || string[0] == '\0') {
   83         return VERS_release;
   84     } else {
   85         switch (string[0]) {
   86           case 'd':
   87               if (__vers_isdigit(string[1])) {
   88                   *string_p = &string[1];
   89                   return VERS_development;
   90               }
   91               break;
   92           case 'a':
   93               if (__vers_isdigit(string[1])) {
   94                   *string_p = &string[1];
   95                   return VERS_alpha;
   96               }
   97               break;
   98           case 'b':
   99               if (__vers_isdigit(string[1])) {
  100                   *string_p = &string[1];
  101                   return VERS_beta;
  102               }
  103               break;
  104           case 'f':
  105               if (__vers_isdigit(string[1])) {
  106                   *string_p = &string[1];
  107                   return VERS_candidate;
  108               } else if (string[1] == 'c' && __vers_isdigit(string[2])) {
  109                   *string_p = &string[2];
  110                   return VERS_candidate;
  111               } else {
  112                   return VERS_invalid;
  113               }
  114               break;
  115           default:
  116               return VERS_invalid;
  117               break;
  118         }
  119     }
  120 
  121     return VERS_invalid;
  122 }
  123 
  124 static char * __VERS_string_for_stage(VERS_stage stage) {
  125     switch (stage) {
  126       case VERS_invalid:     return "?"; break;
  127       case VERS_development: return "d"; break;
  128       case VERS_alpha:       return "a"; break;
  129       case VERS_beta:        return "b"; break;
  130       case VERS_candidate:   return "f"; break;
  131       case VERS_release:     return ""; break;
  132     }
  133 
  134     return "?";
  135 }
  136 
  137 PRIV_EXT
  138 VERS_version VERS_parse_string(const char * vers_string) {
  139     VERS_version result = -1;
  140     int vers_digit = -1;
  141     int num_digits_scanned = 0;
  142     VERS_version vers_major = 0;
  143     VERS_version vers_minor = 0;
  144     VERS_version vers_revision = 0;
  145     VERS_version vers_stage = 0;
  146     VERS_version vers_stage_level = 0;
  147     char * current_char_p;
  148 
  149     if (!vers_string || *vers_string == '\0') {
  150         return -1;
  151     }
  152 
  153     current_char_p = (char *)&vers_string[0];
  154 
  155    /*****
  156     * Check for an initial digit of the major release number.
  157     */
  158     vers_major = __vers_digit_for_char(*current_char_p);
  159     if (vers_major < 0) {
  160         return -1;
  161     }
  162 
  163     current_char_p++;
  164     num_digits_scanned = 1;
  165 
  166    /* Complete scan for major version number. Legal characters are
  167     * any digit, period, any buildstage letter.
  168     */
  169     while (num_digits_scanned < VERS_MAJOR_DIGITS) {
  170         if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  171             vers_stage = VERS_release;
  172             goto finish;
  173         } else if (__vers_isdigit(*current_char_p)) {
  174             vers_digit = __vers_digit_for_char(*current_char_p);
  175             if (vers_digit < 0) {
  176                 return -1;
  177             }
  178             vers_major = (vers_major) * 10 + vers_digit;
  179             current_char_p++;
  180             num_digits_scanned++;
  181         } else if (__VERS_isreleasestate(*current_char_p)) {
  182             goto release_state;
  183         } else if (*current_char_p == '.') {
  184             current_char_p++;
  185             goto minor_version;
  186         } else {
  187             return -1;
  188         }
  189     }
  190 
  191    /* Check for too many digits.
  192     */
  193     if (num_digits_scanned == VERS_MAJOR_DIGITS) {
  194          if (*current_char_p == '.') {
  195             current_char_p++;
  196         } else if (__vers_isdigit(*current_char_p)) {
  197             return -1;
  198         }
  199     }
  200 
  201 minor_version:
  202 
  203     num_digits_scanned = 0;
  204 
  205    /* Scan for minor version number. Legal characters are
  206     * any digit, period, any buildstage letter.
  207     */
  208     while (num_digits_scanned < VERS_MINOR_DIGITS) {
  209         if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  210             vers_stage = VERS_release;
  211             goto finish;
  212         } else if (__vers_isdigit(*current_char_p)) {
  213             vers_digit = __vers_digit_for_char(*current_char_p);
  214             if (vers_digit < 0) {
  215                 return -1;
  216             }
  217             vers_minor = (vers_minor) * 10 + vers_digit;
  218             current_char_p++;
  219             num_digits_scanned++;
  220         } else if (__VERS_isreleasestate(*current_char_p)) {
  221             goto release_state;
  222         } else if (*current_char_p == '.') {
  223             current_char_p++;
  224             goto revision;
  225         } else {
  226             return -1;
  227         }
  228     }
  229 
  230    /* Check for too many digits.
  231     */
  232     if (num_digits_scanned == VERS_MINOR_DIGITS) {
  233          if (*current_char_p == '.') {
  234             current_char_p++;
  235         } else if (__vers_isdigit(*current_char_p)) {
  236             return -1;
  237         }
  238     }
  239 
  240 revision:
  241 
  242     num_digits_scanned = 0;
  243 
  244    /* Scan for revision version number. Legal characters are
  245     * any digit, any buildstage letter (NOT PERIOD).
  246     */
  247     while (num_digits_scanned < VERS_REVISION_DIGITS) {
  248         if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  249             vers_stage = VERS_release;
  250             goto finish;
  251         } else if (__vers_isdigit(*current_char_p)) {
  252             vers_digit = __vers_digit_for_char(*current_char_p);
  253             if (vers_digit < 0) {
  254                 return -1;
  255             }
  256             vers_revision = (vers_revision) * 10 + vers_digit;
  257             current_char_p++;
  258             num_digits_scanned++;
  259         } else if (__VERS_isreleasestate(*current_char_p)) {
  260             goto release_state;
  261         } else {
  262             return -1;
  263         }
  264     }
  265 
  266    /* Check for too many digits.
  267     */
  268     if (num_digits_scanned == VERS_REVISION_DIGITS) {
  269          if (*current_char_p == '.') {
  270             current_char_p++;
  271         } else if (__vers_isdigit(*current_char_p)) {
  272             return -1;
  273         }
  274     }
  275 
  276 release_state:
  277 
  278    /*****
  279     * Check for the release state.
  280     */
  281     if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  282         vers_stage = VERS_release;
  283         goto finish;
  284     } else {
  285         vers_stage = __VERS_stage_for_string(&current_char_p);
  286         if (vers_stage == VERS_invalid) {
  287             return -1;
  288         }
  289     }
  290 
  291 
  292 // stage level
  293 
  294     num_digits_scanned = 0;
  295 
  296    /* Scan for stage level number. Legal characters are
  297     * any digit only.
  298     */
  299     while (num_digits_scanned < VERS_STAGE_LEVEL_DIGITS) {
  300         if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  301             if (num_digits_scanned) {
  302                 goto finish;
  303             } else {
  304                 return -1;
  305             }
  306         } else if (__vers_isdigit(*current_char_p)) {
  307             vers_digit = __vers_digit_for_char(*current_char_p);
  308             if (vers_digit < 0) {
  309                 return -1;
  310             }
  311             vers_stage_level = (vers_stage_level) * 10 + vers_digit;
  312             current_char_p++;
  313             num_digits_scanned++;
  314         } else {
  315             return -1;
  316         }
  317     }
  318 
  319    /* Check for too many digits.
  320     */
  321     if ((num_digits_scanned == VERS_STAGE_LEVEL_DIGITS) &&
  322         ! (__vers_isspace(*current_char_p) || (*current_char_p == '\0'))) {
  323 
  324         return -1;
  325     }
  326 
  327     if (vers_stage_level > 255) {
  328         return -1;
  329     }
  330 
  331 finish:
  332 
  333     if (vers_stage == VERS_candidate && vers_stage_level == 0) {
  334         return -1;
  335     }
  336 
  337     result = (vers_major * VERS_MAJOR_MULT) +
  338              (vers_minor * VERS_MINOR_MULT) +
  339              (vers_revision * VERS_REVISION_MULT) +
  340              (vers_stage * VERS_STAGE_MULT) +
  341              vers_stage_level; 
  342 
  343     return result;
  344 }
  345 
  346 #define VERS_STRING_MAX_LEN  (16)
  347 
  348 PRIV_EXT
  349 int VERS_string(char * buffer, UInt32 length, VERS_version vers) {
  350     int cpos = 0;
  351     VERS_version vers_major = 0;
  352     VERS_version vers_minor = 0;
  353     VERS_version vers_revision = 0;
  354     VERS_version vers_stage = 0;
  355     VERS_version vers_stage_level = 0;
  356     char * stage_string = NULL;  // don't free
  357 
  358    /* No buffer or length less than longest possible vers string,
  359     * return 0.
  360     */
  361     if (!buffer || length < VERS_STRING_MAX_LEN) {
  362         return 0;
  363     }
  364 
  365     bzero(buffer, length * sizeof(char));
  366 
  367     if (vers < 0) {
  368         strcpy(buffer, "(invalid)");
  369         return 1;
  370     }
  371 
  372     vers_major = vers / VERS_MAJOR_MULT;
  373 
  374     vers_minor = vers - (vers_major * VERS_MAJOR_MULT);
  375     vers_minor /= VERS_MINOR_MULT;
  376 
  377     vers_revision = vers -
  378         ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) );
  379     vers_revision /= VERS_REVISION_MULT;
  380 
  381     vers_stage = vers -
  382         ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) +
  383           (vers_revision * VERS_REVISION_MULT));
  384     vers_stage /= VERS_STAGE_MULT;
  385 
  386     vers_stage_level = vers -
  387         ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) +
  388           (vers_revision * VERS_REVISION_MULT) + (vers_stage * VERS_STAGE_MULT));
  389 
  390     cpos = sprintf(buffer, "%lu", (UInt32)vers_major);
  391 
  392    /* Always include the minor version; it just looks weird without.
  393     */
  394     buffer[cpos] = '.';
  395     cpos++;
  396     cpos += sprintf(buffer+cpos, "%lu", (UInt32)vers_minor);
  397 
  398    /* The revision is displayed only if nonzero.
  399     */
  400     if (vers_revision) {
  401         buffer[cpos] = '.';
  402         cpos++;
  403         cpos += sprintf(buffer+cpos, "%lu", (UInt32)vers_revision);
  404     }
  405 
  406     stage_string = __VERS_string_for_stage(vers_stage);
  407     if (stage_string && stage_string[0]) {
  408         strcat(buffer, stage_string);
  409         cpos += strlen(stage_string);
  410     }
  411 
  412     if (vers_stage < VERS_release) {
  413         sprintf(buffer+cpos, "%lu", (UInt32)vers_stage_level);
  414     }
  415 
  416     return 1;
  417 }

Cache object: 68e5a63e68a28791ecf5956b4f9dd674


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.