Annotation of researchv10no/cmd/snocone/oosnocone.sc, revision 1.1

1.1     ! root        1:        data("b(op,l,r)")
        !             2:        data("u(op,r)")
        !             3:        data("i_fcall(name,head,tail)")
        !             4:        data("fcall(name,args,l,r)")
        !             5:        data("argexp(exp,next)")
        !             6:        data("binfo(in,out,lp,rp,slp,srp,fn)")
        !             7: 
        !             8:        stack = table()
        !             9:        bconv = table()
        !            10:        deflist = table(50)
        !            11:        inctab = table()
        !            12:        stno_tab = table(100)
        !            13: 
        !            14:        bconv['('] = binfo('(','',0)
        !            15: 
        !            16:        bconv['='] = binfo('=','=',1,2,0,1)
        !            17:        bconv['?'] = binfo('?','?',2,2,1,1)
        !            18:        bconv['|'] = binfo('|','|',3,3,2,2)
        !            19:        bconv['||'] = or_binfo = binfo('||','',4,4,0,0,1)
        !            20:        bconv['&&'] = cat_binfo = binfo('&&',' ',5,5,4,4)
        !            21:        bconv['>'] = binfo('>','GT',6,6,0,0,1)
        !            22:        bconv['<'] = binfo('<','LT',6,6,0,0,1)
        !            23:        bconv['>='] = binfo('>=','GE',6,6,0,0,1)
        !            24:        bconv['<='] = binfo('<=','LE',6,6,0,0,1)
        !            25:        bconv['=='] = binfo('==','EQ',6,6,0,0,1)
        !            26:        bconv['!='] = binfo('!=','NE',6,6,0,0,1)
        !            27:        bconv['::'] = binfo('::','IDENT',6,6,0,0,1)
        !            28:        bconv[':!:'] = binfo(':!:','DIFFER',6,6,0,0,1)
        !            29:        bconv[':>:'] = binfo(':>:','LGT',6,6,0,0,1)
        !            30:        bconv[':<:'] = binfo(':<:','LLT',6,6,0,0,1)
        !            31:        bconv[':>=:'] = binfo(':>=:','LGE',6,6,0,0,1)
        !            32:        bconv[':<=:'] = binfo(':<=:','LLE',6,6,0,0,1)
        !            33:        bconv[':==:'] = binfo(':==:','LEQ',6,6,0,0,1)
        !            34:        bconv[':!=:'] = binfo(':!=:','LNE',6,6,0,0,1)
        !            35:        bconv['+'] = binfo('+','+',7,7,5,5)
        !            36:        bconv['-'] = binfo('-','-',7,7,5,5)
        !            37:        bconv['/'] = binfo('/','/',8,8,7,7)
        !            38:        bconv['*'] = binfo('*','*',8,8,8,8)
        !            39:        bconv['%'] = binfo('%','REMDR',8,8,0,0,1)
        !            40:        bconv['^'] = binfo('^','**',9,10,10,11)
        !            41:        bconv['.'] = binfo('.','.',10,10,11,11)
        !            42:        bconv['$'] = binfo('$','$',10,10,11,11)
        !            43: 
        !            44:        ht = char(9)
        !            45:        optblank = nspan(" " && ht)
        !            46:        blank = span(" " && ht)
        !            47:        digits = "0123456789"
        !            48:        letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
        !            49: 
        !            50:        integer = span(digits)
        !            51:        exponent = any("eEdD") && (any("+-") | "") && integer
        !            52:        real = integer && "." && (integer | "") && (exponent | "") |
        !            53:                integer && exponent | "." && integer && (exponent | "")
        !            54:        number = real | integer
        !            55: 
        !            56:        string = any("'" && '"') $ squote && break(*squote) && len(1)
        !            57: 
        !            58:        constant = number | string
        !            59:        identifier = any(letters) && nspan(letters && digits)
        !            60:        unaryop = any("+-*&@~?.$")
        !            61:        binaryop = any("+-*/<>=^.$?|%") | "==" | "!=" | "<=" | ">=" | "&&" |
        !            62:                "||" | ":==:" | ":!=:" | ":>:" | ":<:" | ":>=" | ":<=:" |
        !            63:                "::" | ":!:"
        !            64: 
        !            65:        fcall = identifier . *mkfcall() && optblank &&
        !            66:                (("(" && list(*exp . *invoke(.mkarg), optblank && ",") &&
        !            67:                optblank && ")" . *invoke(.endfc)) |
        !            68:                ("[" && list(*exp . *invoke(.mkarg), optblank && ",") &&
        !            69:                optblank && "]" . *invoke(.endfc) . *invoke(.mkarray)))
        !            70: 
        !            71:        term = optblank && (constant . *push() . *dotck() |
        !            72:                identifier . *push() | "(" && *exp && optblank && ")" | fcall)
        !            73:        operand = term | optblank && unaryop . *push() &&
        !            74:                *operand . *invoke(.unop)
        !            75:        exp = "" . *begexp() && *operand &&
        !            76:                arbno(optblank && binaryop . *push() . *invoke(.mkbinfo) &&
        !            77:                *operand . *invoke(.binop)) && "" . *endexp()
        !            78: 
        !            79:        label = optblank && identifier . lab . *emitlab(lab) && optblank && ":"
        !            80: 
        !            81:        clause = fence && arbno(label) && optblank &&
        !            82:                ("if" . cl_type && optblank && "(" && *exp && optblank && ")" |
        !            83:                "while" . cl_type && optblank && "(" && *exp && optblank && ")" |
        !            84:                (kw("return") | kw("freturn") | kw("nreturn")) . cl_type && optblank &&
        !            85:                        ("" . *push() | *exp) &&
        !            86:                        optblank && (any("{}") . del | rpos(0)) |
        !            87:                "go" && optblank && "to" && blank &&
        !            88:                        identifier . dest . *invoke(.gocl) |
        !            89:                ("{" | "}") . cl_type |
        !            90:                ("do" | kw("else")) . cl_type && (span(" " && ht) | rpos(0)) |
        !            91:                "procedure" . cl_type && blank && identifier . fname |
        !            92:                "struct" . cl_type && blank && identifier . stname |
        !            93:                "for" . cl_type && optblank &&
        !            94:                        "(" && *exp && optblank && "," && *exp && optblank &&
        !            95:                        "," && *exp && optblank && ")" |
        !            96:                rpos(0) . cl_type && *invoke(.emiteos) |
        !            97:                *exp && optblank && (any("{}") . del | rpos(0)) . *invoke(.expcl))
        !            98: 
        !            99:        gl_files = table()
        !           100:        gl_lines = table()
        !           101:        gl_vars = table()
        !           102:        gl_index = -1
        !           103: 
        !           104:        emit_stno = 0
        !           105: 
        !           106:        &stlimit = 1000000000
        !           107: #
        !           108: #      save the current state -- we really begin execution here.
        !           109:        exit(3)
        !           110: #
        !           111: #      establish the "object" file
        !           112:        outfile = "a.out"
        !           113:        output(.outf,0,outfile)
        !           114:        outf = "#!/usr/bin/spitbol -s16k"
        !           115: #
        !           116: #      Establish a starting point for input files
        !           117:        gl_arg = host(3) - 1
        !           118:        if (~host (2, host(3))) {
        !           119:                output = "no files"
        !           120:                go to end
        !           121:        }
        !           122: 
        !           123:        if (~gl_nextfile()) {
        !           124:                go to end
        !           125:        }
        !           126: #
        !           127: #      Prologue
        !           128:        emitlab("MAIN.")
        !           129: #
        !           130: #      The main loop.  We expect to read a series of statements.
        !           131:        while (nclause (1)) {
        !           132:                if (ident (cl_type, "procedure"))
        !           133:                        funct()
        !           134:                else if (ident (cl_type, "struct"))
        !           135:                        dostruct()
        !           136:                else
        !           137:                        dostmt()
        !           138:        }
        !           139: 
        !           140: 
        !           141: #      Epilogue
        !           142: exit:
        !           143:        emitg("END")
        !           144:        emitlab("START.")
        !           145:        emit("CODE('START.')")
        !           146:        for (i = 1, i <= deflist[0], i = i + 1) {
        !           147:                emiteos()
        !           148:                emit(deflist[i])
        !           149:        }
        !           150: 
        !           151:        emitg("MAIN.")
        !           152:        emitlab("END")
        !           153:        emit("START.")
        !           154:        emiteos()
        !           155:        endfile(0)
        !           156:        host (1, "chmod +x " && outfile)
        !           157: 
        !           158: 
        !           159: 
        !           160: #                      subroutines
        !           161: 
        !           162: 
        !           163: 
        !           164: 
        !           165: #      like span, but the pattern returned
        !           166: #      can also match the null string
        !           167: procedure nspan (str) {
        !           168:        return span (str) | ""
        !           169: }
        !           170: 
        !           171: #      a pattern that matches a list of zero or more
        !           172: #      "item"s separated by "delim"s
        !           173: procedure list (item, delim) {
        !           174:        return item && arbno (delim && item) | ""
        !           175: }
        !           176: 
        !           177: #      a pattern that matches the keyword given by the
        !           178: #      argument, insisting that it be followed by a non-letter.
        !           179: procedure kw (s) {
        !           180:        return span(letters) $ dummy &&
        !           181:                convert("ident(dummy,'" && s && "')", "EXPRESSION")
        !           182: }
        !           183: 
        !           184: #      return the name of the (new) top stack element
        !           185: procedure push() {
        !           186:        stackptr = stackptr + 1
        !           187:        nreturn  .stack[stackptr]
        !           188: }
        !           189: 
        !           190: #      return the value of the (old) top stack element
        !           191: procedure pop() {
        !           192:        pop = stack[stackptr]
        !           193:        stack[stackptr] = ""
        !           194:        stackptr = stackptr - 1
        !           195: }
        !           196: 
        !           197: #      return the name of the stack element n away from the top
        !           198: procedure peek (n) {
        !           199:        if (n >= stackptr)
        !           200:                go to err
        !           201:        nreturn .stack[stackptr - n]
        !           202: }
        !           203: 
        !           204: #      top()
        !           205: #      return the name of the top stack element
        !           206: procedure top() {
        !           207:        nreturn .stack[stackptr]
        !           208: }
        !           209: 
        !           210: #      isbin(x)
        !           211: #      is x a structure describing a binary operator?
        !           212: #      things like == and ||, which syntactically look
        !           213: #      more like functions than operators in their snobol form,
        !           214: #      are considered not to be operators.
        !           215: procedure isbin (x) {
        !           216:        if (differ (datatype (x), 'B') || differ (fn (op (x))))
        !           217:                freturn
        !           218: }
        !           219: 
        !           220: #      isneg(x)
        !           221: #      is x a structure describing a unary negation operator?
        !           222: procedure isneg (x) {
        !           223:        if (differ (datatype (x), 'U') || differ (op (x), '~'))
        !           224:                freturn
        !           225: }
        !           226: 
        !           227: #
        !           228: #      print an expression in snobol form
        !           229: procedure dprint (x) op, l, r, d, i, del {
        !           230:        d = datatype(x)
        !           231:        if (ident (d, 'STRING')) {
        !           232:                emit (x)
        !           233:                return
        !           234:        }
        !           235: 
        !           236:        if (ident (d, 'U')) {
        !           237:                # unary operator
        !           238:                emit (op (x))
        !           239:                if (isbin(r(x)))
        !           240:                        emit('(')
        !           241:                dprint(r(x))
        !           242:                if (isbin(r(x)))
        !           243:                        emit(')')
        !           244:                return
        !           245:        }
        !           246: 
        !           247: 
        !           248:        if (ident (d, 'FCALL')) {
        !           249:                # function call or array reference
        !           250:                emit (name (x))
        !           251:                emit (l (x))
        !           252:                r = args (x)
        !           253:                while (differ (r)) {
        !           254:                        emit (del)
        !           255:                        dprint (exp (r))
        !           256:                        del = ','
        !           257:                        r = next (r)
        !           258:                }
        !           259:                emit (r (x))
        !           260:                return
        !           261:        }
        !           262: 
        !           263:        if (ident (d, 'B')) {
        !           264:                # binary operator
        !           265:                op = op (x)
        !           266:                if (ident (op, or_binfo)) {
        !           267:                        emit ('(')
        !           268:                        bprint (x)
        !           269:                        emit (')')
        !           270:                        return
        !           271:                }
        !           272:                l = isbin(l(x)) && slp(op(l(x))) < srp(op) && 1 || ""
        !           273:                r = isbin(r(x)) && slp(op) > srp(op(r(x))) && 1 || ""
        !           274: 
        !           275:                # check for [f](a,b)
        !           276:                if (differ (fn (op))) {
        !           277:                        emit(out(op))
        !           278:                        emit('(')
        !           279:                        dprint(l(x))
        !           280:                        emit(',')
        !           281:                        dprint(r(x))
        !           282:                        emit(')')
        !           283:                        return
        !           284:                }
        !           285: 
        !           286:                # ordinary binary operator
        !           287:                if (differ (l))
        !           288:                        emit ('(')
        !           289:                dprint(l(x))
        !           290:                if (differ (l))
        !           291:                        emit (')')
        !           292:                emitb(out(op))
        !           293:                if (differ(r))
        !           294:                        emit('(')
        !           295:                dprint(r(x))
        !           296:                if (differ(r))
        !           297:                        emit(')')
        !           298:                return
        !           299:        }
        !           300: 
        !           301:        # unknown datatype
        !           302:        i = 1
        !           303:        emit(d)
        !           304:        emit ('(')
        !           305:        while (dprint (apply (field (d, i), x))) {
        !           306:                i = i + 1
        !           307:                emit (',')
        !           308:        }
        !           309:        emit (')')
        !           310: }
        !           311: 
        !           312: #      bprint(x)
        !           313: #      subroutine of dprint -- used to handle printing of
        !           314: #      things of the form (a,b), which are inherently
        !           315: #      associative and can therefore be grouped as follows
        !           316: #      ((a,b),c) <=>  (a,(b,c)) <=>  (a,b,c)
        !           317: procedure bprint (x) {
        !           318:        if (differ (datatype(x), 'B') || differ (op(x), or_binfo)) {
        !           319:                dprint (x)
        !           320:                return
        !           321:        }
        !           322:        bprint(l(x))
        !           323:        emit(',')
        !           324:        bprint(r(x))
        !           325: }
        !           326: 
        !           327: #      sprint(x)
        !           328: #      like dprint, but print in a form appropriate for
        !           329: #      an entire statement.  Problem:  if the top level
        !           330: #      operator is a concatenation, it is necessary to
        !           331: #      enclose the whole thing in parentheses, because
        !           332: #      otherwise it would be mistaken for a pattern match.
        !           333: procedure sprint (x) {
        !           334:        if (ident(datatype(x),'B') && ident(op(x),cat_binfo))
        !           335:                emit('(')
        !           336:        dprint(x)
        !           337:        if (ident(datatype(x),'B') && ident(op(x),cat_binfo))
        !           338:                emit(')')
        !           339:        emiteob()
        !           340: }
        !           341: 
        !           342: #      invoke(f)
        !           343: #      call an argument-free function in a context where
        !           344: #      a name is required, such as    arb . *invoke(.foo)
        !           345: procedure invoke (f) {
        !           346:        apply (f)
        !           347:        nreturn .dummy
        !           348: }
        !           349: 
        !           350: #      a unary operator has been detected during parsing
        !           351: procedure unop() r, op {
        !           352:        r = pop()
        !           353:        op = pop()
        !           354:        push() = u(op,r)
        !           355: }
        !           356: 
        !           357: #      mkfcall()
        !           358: #      Parsing has detected the beginning of a function call
        !           359: procedure mkfcall() {
        !           360:        push() = i_fcall()
        !           361:        nreturn .name(top())
        !           362: }
        !           363: 
        !           364: #      parsing has detected an argument to a function
        !           365: procedure mkarg() x, f {
        !           366:        x = argexp(pop(),"")
        !           367:        f = top()
        !           368:        if (differ(tail(f)))
        !           369:                next(tail(f)) = x
        !           370:        tail(f) = x
        !           371:        head(f) = ident(head(f)) && x
        !           372: }
        !           373: 
        !           374: #      parsing has detected the end of a function call
        !           375: procedure endfc() f {
        !           376:        f = pop()
        !           377:        push() = fcall(name(f),head(f),'(',')')
        !           378: }
        !           379: 
        !           380: #      the fcall at the head of the stack is really an array
        !           381: procedure mkarray() t {
        !           382:        t = top()
        !           383:        l(t) = '<'
        !           384:        r(t) = '>'
        !           385: }
        !           386: 
        !           387: #      the beginning of an expression has been detected
        !           388: procedure begexp() {
        !           389:        push() = bconv['(']
        !           390:        nreturn .dummy
        !           391: }
        !           392: 
        !           393: #      a binary operator has been detected.  We handle
        !           394: #      precedence here rather than in the grammar
        !           395: #      because it is less work.
        !           396: procedure binop() l, r, op, newr, newop {
        !           397:        while (lp(peek(3)) >= rp(peek(1))) {
        !           398:                newr = pop()
        !           399:                newop = pop()
        !           400:                r = pop()
        !           401:                op = pop()
        !           402:                l = pop()
        !           403:                push() = b(op,l,r)
        !           404:                push() = newop
        !           405:                push() = newr
        !           406:        }
        !           407: }
        !           408: 
        !           409: #      the end of an expression has been detected
        !           410: procedure endexp() l, r, op {
        !           411:        while (differ (in (peek (1)), '(')) {
        !           412:                r = pop()
        !           413:                op = pop()
        !           414:                l = pop()
        !           415:                push() = b(op,l,r)
        !           416:        }
        !           417:        r = pop()
        !           418:        pop()
        !           419:        push() = r
        !           420:        nreturn .dummy
        !           421: }
        !           422: 
        !           423: #      catenate x and y, making sure that at least one
        !           424: #      blank separate them.
        !           425: procedure bcat (x, y) {
        !           426:        if (ident (x))
        !           427:                return y
        !           428:        if (ident (y))
        !           429:                return x
        !           430:        if (substr (x, size(x), 1) :==: ' ' || substr (y, 1, 1) :==: ' ')
        !           431:                return x && y
        !           432:        return x && ' ' && y
        !           433: }
        !           434: 
        !           435: #      locate the binfo structure that describes the
        !           436: #      binary operator whose input character representation
        !           437: #      has been placed on the top of the stack.
        !           438: procedure mkbinfo() op {
        !           439:        op = bconv[pop()]
        !           440:        if (ident(op))
        !           441:                go to err
        !           442:        push() = op
        !           443: }
        !           444: 
        !           445: #      dotck()
        !           446: #      if necessary, append a leading zero to a floating-point
        !           447: #      constant that begins with a decimal point.  The idea
        !           448: #      that .5 is syntactically correct but semantically illegal
        !           449: #      is just too scary to leave in.
        !           450: procedure dotck() {
        !           451:        top() ? fence && '.' = '0.'
        !           452:        nreturn .dummy
        !           453: }
        !           454: 
        !           455: #      write label l to the output
        !           456: procedure emitlab (l) {
        !           457:        if (differ(l)) {
        !           458:                emiteos()
        !           459:                st_lab = l
        !           460:        }
        !           461:        nreturn .dummy
        !           462: }
        !           463: 
        !           464: #      put string s in the output
        !           465: procedure emit (s) {
        !           466:        if (differ(emit_eob))
        !           467:                emiteos()
        !           468:        st_body = st_body && s
        !           469: }
        !           470: 
        !           471: #      we are done with the body of the generated statement
        !           472: procedure emiteob() {
        !           473:        emit_eob = 1
        !           474:        stno_tab[emit_stno] = gl_file && "(" && gl_line && ")"
        !           475: }
        !           476: 
        !           477: #      write success branch l
        !           478: procedure emits (l) {
        !           479:        emiteob()
        !           480:        st_s = l
        !           481: }
        !           482: 
        !           483: #      emitf(l)
        !           484: #      write failure branch l
        !           485: procedure emitf (l) {
        !           486:        emiteob()
        !           487:        st_f = l
        !           488: }
        !           489: 
        !           490: #      write unconditional branch l
        !           491: procedure emitg (l) {
        !           492:        emiteob()
        !           493:        st_s = ident(st_s) && l
        !           494:        st_f = ident(st_f) && l
        !           495: }
        !           496: 
        !           497: #      write s surrounded by blanks
        !           498: procedure emitb (s) {
        !           499:        emit(' ')
        !           500:        if (differ (s, ' ')) {
        !           501:                emit (s)
        !           502:                emit(' ')
        !           503:        }
        !           504: }
        !           505: 
        !           506: #      emiteos()out,goto
        !           507: #      we are done with the entire statement
        !           508: procedure emiteos() out, goto, s, del {
        !           509:        emit_eob = ""
        !           510:        emit_stno = emit_stno + 1
        !           511:        if (differ(st_lab) || differ(st_body) || differ(st_s) || differ(st_f)) {
        !           512:                out = st_lab && ht && st_body
        !           513:                out = out && dupl (ht,5 - size(st_lab) / 8 - size(st_body) / 8)
        !           514:                if (differ (st_s) || differ (st_f)) {
        !           515:                        goto = ht && ':'
        !           516:                        if (ident (st_s, st_f))
        !           517:                                goto = goto && "(" && st_s && ")"
        !           518:                        else {
        !           519:                                if (differ (st_s))
        !           520:                                        goto = goto && "S(" && st_s && ")"
        !           521:                                if (differ (st_f))
        !           522:                                        goto = goto && "F(" && st_f && ")"
        !           523:                        }
        !           524:                }
        !           525:                out = out && goto
        !           526:                while (size(out) >= 70) {
        !           527:                        out ? fence &&
        !           528:                                (arbno(break(" '" && '"') &&
        !           529:                                (" " | any("'" && '"') $ del &&
        !           530:                                break(*del) && len(1))) $ s &&
        !           531:                                *(size(s) > 50)) . outf = "+    "
        !           532:                }
        !           533:                outf = out
        !           534:                st_lab = st_body = st_s = st_f = ""
        !           535:        }
        !           536: }
        !           537: 
        !           538: # attempt to read an input line, taking #include into account
        !           539: procedure getline() x, file, del, dir {
        !           540:        do {
        !           541:                # Try to read a line from the current file
        !           542:                while (x = $gl_var) {
        !           543: 
        !           544:                        # We have a line: count it
        !           545:                        gl_line = gl_line + 1
        !           546: 
        !           547:                        # If it's not an include statement, we're done.
        !           548:                        if (~(x ? fence && "#" && *optblank && "include" &&
        !           549:                            *optblank && any('"<{' && "'") $ del &&
        !           550:                            break(*replace(del,'<{','>}')) . file &&
        !           551:                            len (1) && *optblank && rpos(0)))
        !           552:                                return x
        !           553: 
        !           554:                        # If the name is enclosed in quotes and
        !           555:                        # relative, then it is relative to the
        !           556:                        # directory containing the currently included
        !           557:                        # file, if any.  If it is enclosed in brackets,
        !           558:                        # it is relative to a canonical directory.
        !           559:                        if ("'" && '"' ? del) {
        !           560:                                if (substr (file, 1, 1) :!=: '/') {
        !           561:                                        if ((gl_file && '/') ? fence &&
        !           562:                                            (breakx('/') && len(1)) . dir &&
        !           563:                                            break('/') && len(1) && rpos(0))
        !           564:                                                file = dir && file
        !           565:                                }
        !           566:                        } else
        !           567:                                file = "/usr/lib/snocone/" && file
        !           568: 
        !           569:                        # If the name was enclosed by single quotes
        !           570:                        # or set brackets, ensure the particular file
        !           571:                        # was included only once.  Right now, we're pretty
        !           572:                        # literal-minded about when two files are really
        !           573:                        # the same:  'x' and './x' are different, for instance.
        !           574:                        if (('"<' ? del) || ident (inctab[file])) {
        !           575:                                inctab[file] = 1
        !           576:                                gl_open (file)
        !           577:                        }
        !           578:                }
        !           579: 
        !           580:                # We've reached the end of this file.
        !           581:                gl_close()
        !           582:        } while (gl_index >= 0 || gl_nextfile());
        !           583: 
        !           584:        freturn
        !           585: }
        !           586: 
        !           587: procedure gl_nextfile() {
        !           588:        gl_arg = gl_arg + 1
        !           589:        if (~gl_open (host (2, gl_arg)))
        !           590:                freturn
        !           591: }
        !           592: 
        !           593: procedure gl_close() {
        !           594:        &errlimit = &errlimit + 1
        !           595:        if (endfile (gl_var))
        !           596:                &errlimit = &errlimit - 1
        !           597:        gl_index = gl_index - 1
        !           598:        gl_file = gl_files[gl_index]
        !           599:        gl_line = gl_lines[gl_index]
        !           600:        gl_var = gl_vars[gl_index]
        !           601:        gl_files[gl_index] = gl_lines[gl_index] = gl_vars[gl_index] = ""
        !           602: }
        !           603: 
        !           604: procedure gl_open (file) {
        !           605:        gl_files[gl_index] = gl_file
        !           606:        gl_lines[gl_index] = gl_line
        !           607:        gl_vars[gl_index] = gl_var
        !           608:        gl_index = gl_index + 1
        !           609:        gl_count = gl_count + 1
        !           610:        gl_var = .$("GL_" && gl_count)
        !           611:        gl_line = 0
        !           612:        gl_file = file
        !           613:        input (gl_var, gl_var, file)
        !           614:        &errlimit = &errlimit + 1
        !           615:        if (rewind (gl_var)) {
        !           616:                &errlimit = &errlimit - 1
        !           617:                return
        !           618:        }
        !           619:        gl_close()
        !           620:        output = "cannot open " && file
        !           621:        freturn
        !           622: }
        !           623: 
        !           624: # attempt to read an input line, return on ultimate failure
        !           625: procedure getinput() del, line {
        !           626: 
        !           627:        # have we already encountered the last EOF?
        !           628:        if (differ (gi_eof))
        !           629:                freturn
        !           630: 
        !           631:        if (line = line && getline()) {
        !           632: 
        !           633:                # strip comments
        !           634:                line ?
        !           635:                    fence &&
        !           636:                        (arbno (break ("'" && '"') &&
        !           637:                            len(1) $ del && break (*del) && len(1)) &&
        !           638:                        break ("'" && '"#')) . line && "#"
        !           639:                
        !           640:                # check for continuation
        !           641:                if (line? any("@$%^&*(-+=[<>|~,?:") && optblank && rpos(0))
        !           642:                        line = line && getinput()
        !           643: 
        !           644:                return line
        !           645:        }
        !           646: 
        !           647:        # we're out of input - signal final eof
        !           648:        gi_eof = 1
        !           649:        freturn
        !           650: }
        !           651: 
        !           652: #      phrase()
        !           653: #      return the next phrase from the input
        !           654: procedure phrase() del {
        !           655:        if (ph_buf ? fence && optblank && rpos(0)) {
        !           656:                if (ph_buf = phbuf && getinput())
        !           657:                        return phrase()
        !           658:                else
        !           659:                        freturn
        !           660:        }
        !           661: 
        !           662:        if (ph_buf ? fence && arbno(break('"' && "';") && fence &&
        !           663:            (any('"' && "'")$del && break(*del) && len(1) |
        !           664:            "")).phrase && ';'  = '')
        !           665:                return
        !           666:        phrase = ph_buf
        !           667:        ph_buf = ''
        !           668: }
        !           669: 
        !           670: #      return a new label
        !           671: procedure newlab() {
        !           672:        nl_count = nl_count + 1
        !           673:        return "L." && nl_count
        !           674: }
        !           675: 
        !           676: #      return a new label and place it on the current statement.
        !           677: #      If the current statement already has a label, use that.
        !           678: procedure marklab() {
        !           679:        if (differ (st_lab) && ident (emit_eob))
        !           680:                return st_lab
        !           681:        marklab = newlab()
        !           682:        emitlab (marklab)
        !           683: }
        !           684: 
        !           685: #      little routines to indicate what type of clause was read
        !           686: 
        !           687: #      expression clause
        !           688: procedure expcl() {
        !           689:        cl_type = "exp"
        !           690: }
        !           691: 
        !           692: #      goto clause
        !           693: procedure gocl() {
        !           694:        cl_type = "goto"
        !           695: }
        !           696: 
        !           697: #      read a new clause and classify it
        !           698: #      if end of input, error unless "okeof" argument is non-null,
        !           699: #      in which case we merely fail
        !           700: #      if rep_clause is set, give us the last clause again
        !           701: procedure nclause (okeof) del {
        !           702: nclause_start:
        !           703:        if (differ (rep_clause)) {
        !           704:                rep_clause = ""
        !           705:                if (ident (eof))
        !           706:                        return
        !           707:                else
        !           708:                        freturn
        !           709:        }
        !           710:        if (linebuf ? fence && *optblank && rpos(0)) {
        !           711:                if (linebuf = phrase())
        !           712:                        go to nclause_start
        !           713: 
        !           714:                #       end of input
        !           715:                if (ident(okeof)) {
        !           716:                        error ('premature EOF')
        !           717:                        go to exit
        !           718:                }
        !           719:                eof = 1
        !           720:                        freturn
        !           721:        }
        !           722: 
        !           723:        #       we really have some input
        !           724:        if (linebuf ? clause = del)
        !           725:                return
        !           726:        error("syntax error")
        !           727:        linebuf = ""
        !           728:        go to nclause_start
        !           729: }
        !           730: 
        !           731: procedure error (msg) {
        !           732:        terminal = gl_file && "(" && gl_line && "): " && msg
        !           733:        &code = 1
        !           734: }
        !           735: 
        !           736: #      handle a statement
        !           737: procedure dostmt() lab, lab2, e1, e2, e3, flip {
        !           738:        if (ident(cl_type,"exp")) {
        !           739:                #       The clause is an expression,
        !           740:                #       so that's the whole statement
        !           741:                sprint(pop())
        !           742:                return
        !           743:        }
        !           744: 
        !           745:        #       It might be a sequence of statements in braces
        !           746:        if (ident(cl_type,"{")) {
        !           747:                nclause()
        !           748:                while (differ (cl_type, "}")) {
        !           749:                        dostmt()
        !           750:                        nclause()
        !           751:                }
        !           752:                return
        !           753:        }
        !           754: 
        !           755:        #       It might be a goto statement
        !           756:        if (ident (cl_type, "goto")) {
        !           757:                emitg (dest)
        !           758:                return
        !           759:        }
        !           760: 
        !           761:        #       It might be an if statement
        !           762:        if (ident(cl_type,"if")) {
        !           763:                e1 = pop()
        !           764: 
        !           765:                # optimize "if (~expr)"
        !           766:                if (isneg (e1)) {
        !           767:                        flip = 1
        !           768:                        e1 = r(e1)
        !           769:                }
        !           770: 
        !           771:                sprint(e1)
        !           772: 
        !           773:                #       Check for if(...)goto
        !           774:                nclause()
        !           775:                if (ident(cl_type,"goto")) {
        !           776:                        if (ident (flip))
        !           777:                                emits(dest)
        !           778:                        else
        !           779:                                emitf(dest)
        !           780: 
        !           781:                        #       In the case of if (e) goto l; else ...
        !           782:                        #       we can pretend the else wasn't there
        !           783:                        if (~nclause(1) || differ (cl_type, "else")) {
        !           784:                                rep_clause = 1
        !           785:                                emitlab (lab)
        !           786:                                return
        !           787:                        }
        !           788:                        nclause()
        !           789:                        dostmt()
        !           790:                        return
        !           791:                }
        !           792: 
        !           793:                #       Not if...goto, emit conditional jump over
        !           794:                #       the statement which follows.
        !           795:                lab = newlab()
        !           796:                if (ident (flip))
        !           797:                        emitf(lab)
        !           798:                else
        !           799:                        emits(lab)
        !           800:                dostmt()
        !           801: 
        !           802:                #       Check for else clause
        !           803:                if (nclause (1) && ident (cl_type, "else")) {
        !           804: 
        !           805:                        #       There is indeed an else clause
        !           806:                        lab2 = newlab()
        !           807:                        emitg(lab2)
        !           808:                        emitlab(lab)
        !           809:                        nclause()
        !           810:                        dostmt()
        !           811:                        emitlab(lab2)
        !           812:                        return
        !           813:                }
        !           814: 
        !           815:                #       No else clause; we must look at this clause again later
        !           816:                rep_clause = 1
        !           817:                emitlab(lab)
        !           818:                return
        !           819:        }
        !           820: 
        !           821:        #       Check for a while clause
        !           822:        if (ident(cl_type,"while")) {
        !           823:                lab = marklab()
        !           824: 
        !           825:                # optimize "while(~exp)"
        !           826:                e1 = pop()
        !           827:                if (isneg (e1)) {
        !           828:                        flip = 1
        !           829:                        e1 = r(e1)
        !           830:                }
        !           831: 
        !           832:                sprint(e1)
        !           833:                lab2 = newlab()
        !           834:                if (ident (flip))
        !           835:                        emitf(lab2)
        !           836:                else
        !           837:                        emits(lab2)
        !           838:                nclause()
        !           839:                dostmt()
        !           840:                emitg(lab)
        !           841:                emitlab(lab2)
        !           842:                return
        !           843:        }
        !           844: 
        !           845:        #       Check for a do clause
        !           846:        if (ident(cl_type,"do")) {
        !           847:                lab = marklab()
        !           848:                nclause()
        !           849:                dostmt()
        !           850:                nclause()
        !           851:                if (differ(cl_type,"while")) {
        !           852:                        error ("expected 'while', found " && cl_type)
        !           853:                        rep_clause = 1
        !           854:                        return
        !           855:                }
        !           856:                e1 = pop()
        !           857:                if (isneg (e1)) {
        !           858:                        flip = 1
        !           859:                        e1 = r (e1)
        !           860:                }
        !           861:                sprint(e1)
        !           862:                if (ident (flip))
        !           863:                        emits (lab)
        !           864:                else
        !           865:                        emitf (lab)
        !           866:                return
        !           867:        }
        !           868: 
        !           869:        #       Check for a "for" clause
        !           870:        if (ident(cl_type,"for")) {
        !           871:                e3 = pop()
        !           872:                e2 = pop()
        !           873:                e1 = pop()
        !           874:                sprint(e1)
        !           875:                emiteob()
        !           876:                lab = marklab()
        !           877:                lab2 = newlab()
        !           878:                if (isneg (e2)) {
        !           879:                        flip = 1
        !           880:                        e2 = r (e2)
        !           881:                }
        !           882:                sprint(e2)
        !           883:                if (ident (flip))
        !           884:                        emitf (lab2)
        !           885:                else
        !           886:                        emits (lab2)
        !           887:                nclause()
        !           888:                dostmt()
        !           889:                sprint(e3)
        !           890:                emitg(lab)
        !           891:                emitlab(lab2)
        !           892:                return
        !           893:        }
        !           894: 
        !           895:        #       could be some kind of return statement
        !           896:        if (cl_type ? "return") {
        !           897:                e1 = pop()
        !           898:                if (differ(e1)) {
        !           899:                        if (differ(fname))
        !           900:                                e1 = b(bconv["="],fname,e1)
        !           901:                        sprint(e1)
        !           902:                }
        !           903:                emitg (replace(cl_type,
        !           904:                        "abcdefghijklmnopqrstuvwxyz",
        !           905:                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
        !           906:                return
        !           907:        }
        !           908: 
        !           909:        #       could even be a null statement
        !           910:        if (ident(cl_type))
        !           911:                return
        !           912: 
        !           913:        error("bad " && cl_type && " clause, ignored")
        !           914: }
        !           915: 
        !           916: #      We have seen "struct" -- parse the 'declaration'
        !           917: procedure dostruct() args {
        !           918:        if (expect ('{')) {
        !           919:                args = getlist ('}')
        !           920:                deflist[deflist[0] = deflist[0] + 1] =
        !           921:                        "DATA('" && stname && "(" && args && ")')"
        !           922:        } else
        !           923:                error ("bad structure definition")
        !           924:        expect ('}')
        !           925: }
        !           926: 
        !           927: #      We have seen "procedure" -- we must now parse the header
        !           928: procedure funct() args, locals, flabel {
        !           929:        if (expect('(')) {
        !           930:                if (~(args = getlist(')')))
        !           931:                        go to fu_error
        !           932:                expect(')')
        !           933:                if (~(locals = getlist('{')))
        !           934:                        go to fu_error
        !           935:        }
        !           936: 
        !           937:        deflist[deflist[0] = deflist[0] + 1] =
        !           938:                "DEFINE('" && fname && '(' && args && ')' && locals && "')"
        !           939: 
        !           940:        #       if we just emitted the end of a previous procedure,
        !           941:        #       we can jump around this one in one go
        !           942:        if (ident (emit_eob) && st_lab ? ".END") {
        !           943:                flabel = st_lab
        !           944:                st_lab = ""
        !           945:                emitlab(fname)
        !           946:                nclause()
        !           947:                dostmt()
        !           948:                emitg("RETURN")
        !           949:                emitlab(flabel)
        !           950:                return
        !           951:        }
        !           952: 
        !           953:        emitg(fname && '.END')
        !           954:        emitlab(fname)
        !           955:        nclause()
        !           956:        dostmt()
        !           957:        emitg("RETURN")
        !           958:        emitlab(fname && '.END')
        !           959:        return
        !           960: 
        !           961: fu_error:
        !           962:        error("bad function definition")
        !           963: }
        !           964: 
        !           965: #      the input should now contain something matching "p"
        !           966: #      possibly surrounded by white space.  If not, fail
        !           967: procedure expect (p) {
        !           968: 
        !           969:        # throw away blank lines
        !           970:        while (linebuf ? fence && optblank && rpos (0)) {
        !           971:                if (~(linebuf = phrase()))
        !           972:                        freturn
        !           973:        }
        !           974: 
        !           975:        # try to match the given pattern, possibly preceded by white space
        !           976:        if (linebuf ? fence && optblank && *p = "")
        !           977:                return
        !           978: 
        !           979:        # didn't match: fail
        !           980:        freturn
        !           981: }
        !           982: 
        !           983: #      expect an identifier in the input; return it.
        !           984: procedure getid() {
        !           985:        if (expect (*identifier . getid))
        !           986:                return
        !           987:        freturn
        !           988: }
        !           989: 
        !           990: #      expect a list of identifiers followed by tail
        !           991: procedure getlist (tail) del {
        !           992: getlist_start:
        !           993:        if (expect(tail)) {
        !           994:                linebuf = tail && linebuf
        !           995:                return
        !           996:        }
        !           997:        if (getlist = getlist && del && getid()) {
        !           998:                expect(',')
        !           999:                del = ','
        !          1000:                go to getlist_start
        !          1001:        }
        !          1002:        if (expect(tail))
        !          1003:                return
        !          1004:        freturn
        !          1005: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.